644 lines
16 KiB
C#
644 lines
16 KiB
C#
|
//
|
||
|
// System.Data.Common.Key.cs
|
||
|
//
|
||
|
// Author:
|
||
|
// Boris Kirzner <borisk@mainsoft.com>
|
||
|
// Konstantin Triger (kostat@mainsoft.com)
|
||
|
//
|
||
|
|
||
|
/*
|
||
|
* Copyright (c) 2002-2004 Mainsoft Corporation.
|
||
|
*
|
||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||
|
* copy of this software and associated documentation files (the "Software"),
|
||
|
* to deal in the Software without restriction, including without limitation
|
||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||
|
* Software is furnished to do so, subject to the following conditions:
|
||
|
*
|
||
|
* The above copyright notice and this permission notice shall be included in
|
||
|
* all copies or substantial portions of the Software.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||
|
* DEALINGS IN THE SOFTWARE.
|
||
|
*/
|
||
|
|
||
|
using System;
|
||
|
using System.Collections;
|
||
|
|
||
|
using System.Text;
|
||
|
|
||
|
namespace System.Data.Common
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// Summary description for Index.
|
||
|
/// </summary>
|
||
|
internal class Index {
|
||
|
#region Fields
|
||
|
|
||
|
static readonly int [] empty = new int [0];
|
||
|
|
||
|
int [] _array;
|
||
|
int _size;
|
||
|
Key _key;
|
||
|
int _refCount;
|
||
|
|
||
|
// Implement a tri-state, with the property that 'know_no_duplicates' has meaning only when '!know_have_duplicates'
|
||
|
bool know_have_duplicates, know_no_duplicates;
|
||
|
|
||
|
#endregion // Fields
|
||
|
|
||
|
#region Constructors
|
||
|
|
||
|
internal Index (Key key)
|
||
|
{
|
||
|
_key = key;
|
||
|
Reset ();
|
||
|
}
|
||
|
|
||
|
#endregion // Constructors
|
||
|
|
||
|
#region Properties
|
||
|
|
||
|
internal Key Key {
|
||
|
get { return _key; }
|
||
|
}
|
||
|
|
||
|
internal int Size {
|
||
|
get { return _size; }
|
||
|
}
|
||
|
|
||
|
internal int RefCount {
|
||
|
get { return _refCount; }
|
||
|
}
|
||
|
|
||
|
internal int IndexToRecord (int index)
|
||
|
{
|
||
|
return index < 0 ? index : _array [index];
|
||
|
}
|
||
|
|
||
|
internal bool HasDuplicates {
|
||
|
get {
|
||
|
if (!know_have_duplicates && !know_no_duplicates) {
|
||
|
for (int i = 0; i < _size - 1; i++) {
|
||
|
if (Key.CompareRecords (_array [i], _array [i + 1]) == 0) {
|
||
|
know_have_duplicates = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
know_no_duplicates = !know_have_duplicates;
|
||
|
}
|
||
|
return know_have_duplicates;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endregion // Properties
|
||
|
|
||
|
#region Methods
|
||
|
|
||
|
internal int [] Duplicates {
|
||
|
get {
|
||
|
if (!HasDuplicates)
|
||
|
return null;
|
||
|
|
||
|
ArrayList dups = new ArrayList ();
|
||
|
|
||
|
bool inRange = false;
|
||
|
for (int i = 0; i < _size - 1; i++) {
|
||
|
if (Key.CompareRecords (_array [i], _array [i + 1]) == 0) {
|
||
|
if (!inRange) {
|
||
|
dups.Add (_array [i]);
|
||
|
inRange = true;
|
||
|
}
|
||
|
|
||
|
dups.Add (_array [i + 1]);
|
||
|
} else {
|
||
|
inRange = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return (int []) dups.ToArray (typeof (int));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal int [] GetAll ()
|
||
|
{
|
||
|
return _array;
|
||
|
}
|
||
|
|
||
|
internal DataRow [] GetAllRows ()
|
||
|
{
|
||
|
DataRow [] list = new DataRow [_size];
|
||
|
for (int i = 0; i < _size; ++i)
|
||
|
list [i] = Key.Table.RecordCache [_array [i]];
|
||
|
return list;
|
||
|
}
|
||
|
|
||
|
internal DataRow [] GetDistinctRows ()
|
||
|
{
|
||
|
ArrayList list = new ArrayList ();
|
||
|
list.Add (Key.Table.RecordCache [_array [0]]);
|
||
|
int currRecord = _array [0];
|
||
|
for (int i = 1; i < _size; ++i) {
|
||
|
if (Key.CompareRecords (currRecord, _array [i]) == 0)
|
||
|
continue;
|
||
|
list.Add (Key.Table.RecordCache [_array [i]]);
|
||
|
currRecord = _array [i];
|
||
|
}
|
||
|
return (DataRow []) list.ToArray (typeof (DataRow));
|
||
|
}
|
||
|
|
||
|
internal void Reset ()
|
||
|
{
|
||
|
_array = empty;
|
||
|
_size = 0;
|
||
|
RebuildIndex ();
|
||
|
}
|
||
|
|
||
|
private void RebuildIndex ()
|
||
|
{
|
||
|
int rows_upperbound = Key.Table.RecordCache.CurrentCapacity;
|
||
|
|
||
|
if (rows_upperbound == 0)
|
||
|
return;
|
||
|
|
||
|
// consider better capacity approximation
|
||
|
_array = new int [rows_upperbound];
|
||
|
_size = 0;
|
||
|
foreach (DataRow row in Key.Table.Rows) {
|
||
|
int record = Key.GetRecord (row);
|
||
|
if (record != -1)
|
||
|
_array [_size++] = record;
|
||
|
}
|
||
|
know_have_duplicates = know_no_duplicates = false;
|
||
|
Sort ();
|
||
|
know_no_duplicates = !know_have_duplicates;
|
||
|
}
|
||
|
|
||
|
private void Sort ()
|
||
|
{
|
||
|
//QuickSort(_array,0,_size-1);
|
||
|
MergeSort (_array, _size);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Returns record number of the record equal to the key values supplied
|
||
|
* in the meaning of index key, or -1 if no equal record found.
|
||
|
*/
|
||
|
internal int Find (object [] keys)
|
||
|
{
|
||
|
int index = FindIndex (keys);
|
||
|
return IndexToRecord (index);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Returns record index (location) of the record equal to the key values supplied
|
||
|
* in the meaning of index key, or -1 if no equal record found.
|
||
|
*/
|
||
|
internal int FindIndex (object [] keys)
|
||
|
{
|
||
|
if (keys == null || keys.Length != Key.Columns.Length)
|
||
|
throw new ArgumentException("Expecting " + Key.Columns.Length + " value(s) for the key being indexed, " +
|
||
|
"but received " + ((keys == null) ? 0 : keys.Length) + " value(s).");
|
||
|
|
||
|
int tmp = Key.Table.RecordCache.NewRecord ();
|
||
|
try {
|
||
|
// init key values for temporal record
|
||
|
for (int i = 0; i < Key.Columns.Length; i++)
|
||
|
Key.Columns [i].DataContainer [tmp] = keys [i];
|
||
|
return FindIndex (tmp);
|
||
|
} finally {
|
||
|
Key.Table.RecordCache.DisposeRecord (tmp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Returns record number of the record equal to the record supplied
|
||
|
* in the meaning of index key, or -1 if no equal record found.
|
||
|
*/
|
||
|
internal int Find (int record)
|
||
|
{
|
||
|
int index = FindIndex (record);
|
||
|
return IndexToRecord (index);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Returns array of record numbers of the records equal equal to the key values supplied
|
||
|
* in the meaning of index key, or -1 if no equal record found.
|
||
|
*/
|
||
|
internal int [] FindAll (object [] keys)
|
||
|
{
|
||
|
int [] indexes = FindAllIndexes (keys);
|
||
|
IndexesToRecords (indexes);
|
||
|
return indexes;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Returns array of indexes of the records inside the index equal equal to the key values supplied
|
||
|
* in the meaning of index key, or -1 if no equal record found.
|
||
|
*/
|
||
|
internal int [] FindAllIndexes (object [] keys)
|
||
|
{
|
||
|
if (keys == null || keys.Length != Key.Columns.Length)
|
||
|
throw new ArgumentException("Expecting " + Key.Columns.Length + " value(s) for the key being indexed," +
|
||
|
"but received " + ((keys == null) ? 0 : keys.Length) + " value(s).");
|
||
|
|
||
|
int tmp = Key.Table.RecordCache.NewRecord ();
|
||
|
try {
|
||
|
// init key values for temporal record
|
||
|
for (int i = 0; i < Key.Columns.Length; i++)
|
||
|
Key.Columns [i].DataContainer [tmp] = keys [i];
|
||
|
return FindAllIndexes (tmp);
|
||
|
} catch (FormatException) {
|
||
|
return empty;
|
||
|
} catch (InvalidCastException) {
|
||
|
return empty;
|
||
|
} finally {
|
||
|
Key.Table.RecordCache.DisposeRecord (tmp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Returns array of record numbers of the records equal to the record supplied
|
||
|
* in the meaning of index key, or empty list if no equal records found.
|
||
|
*/
|
||
|
internal int [] FindAll (int record)
|
||
|
{
|
||
|
int [] indexes = FindAllIndexes (record);
|
||
|
IndexesToRecords (indexes);
|
||
|
return indexes;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Returns array of indexes of the records inside the index that equal to the record supplied
|
||
|
* in the meaning of index key, or empty list if no equal records found.
|
||
|
*/
|
||
|
internal int [] FindAllIndexes (int record)
|
||
|
{
|
||
|
int index = FindIndex (record);
|
||
|
if (index == -1)
|
||
|
return empty;
|
||
|
|
||
|
int startIndex = index++;
|
||
|
int endIndex = index;
|
||
|
|
||
|
for (; startIndex >= 0 && Key.CompareRecords (_array [startIndex], record) == 0; startIndex--) {
|
||
|
}
|
||
|
for (; endIndex < _size && Key.CompareRecords (_array [endIndex], record) == 0; endIndex++) {
|
||
|
}
|
||
|
|
||
|
int length = endIndex - startIndex - 1;
|
||
|
int [] indexes = new int [length];
|
||
|
|
||
|
for (int i = 0; i < length; i++)
|
||
|
indexes [i] = ++startIndex;
|
||
|
|
||
|
return indexes;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Returns index inside the array where record number of the record equal to the record supplied
|
||
|
* in the meaning of index key is sored, or -1 if no equal record found.
|
||
|
*/
|
||
|
private int FindIndex (int record)
|
||
|
{
|
||
|
if (_size == 0)
|
||
|
return -1;
|
||
|
return BinarySearch (_array, 0, _size - 1, record);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Finds exact location of the record specified
|
||
|
*/
|
||
|
private int FindIndexExact (int record)
|
||
|
{
|
||
|
for (int i = 0, size = _size; i < size; i++)
|
||
|
if (_array [i] == record)
|
||
|
return i;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Returns array of records from the indexes (locations) inside the index
|
||
|
*/
|
||
|
private void IndexesToRecords (int [] indexes)
|
||
|
{
|
||
|
for (int i = 0; i < indexes.Length; i++)
|
||
|
indexes [i] = _array [indexes [i]];
|
||
|
}
|
||
|
|
||
|
internal void Delete (DataRow row)
|
||
|
{
|
||
|
int oldRecord = Key.GetRecord (row);
|
||
|
Delete (oldRecord);
|
||
|
}
|
||
|
|
||
|
internal void Delete (int oldRecord)
|
||
|
{
|
||
|
if (oldRecord == -1)
|
||
|
return;
|
||
|
|
||
|
int index = FindIndexExact (oldRecord);
|
||
|
if (index != -1) {
|
||
|
if (know_have_duplicates) {
|
||
|
int c1 = 1;
|
||
|
int c2 = 1;
|
||
|
|
||
|
if (index > 0)
|
||
|
c1 = Key.CompareRecords (_array [index - 1], oldRecord);
|
||
|
if (index < _size - 1)
|
||
|
c2 = Key.CompareRecords (_array [index + 1], oldRecord);
|
||
|
|
||
|
if (c1 == 0 ^ c2 == 0)
|
||
|
know_have_duplicates = know_no_duplicates = false;
|
||
|
}
|
||
|
Remove (index);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void Remove (int index)
|
||
|
{
|
||
|
if (_size > 1)
|
||
|
System.Array.Copy (_array, index + 1, _array, index, _size - index - 1);
|
||
|
_size--;
|
||
|
}
|
||
|
|
||
|
internal void Update (DataRow row, int oldRecord, DataRowVersion oldVersion, DataRowState oldState)
|
||
|
{
|
||
|
bool contains = Key.ContainsVersion (oldState, oldVersion);
|
||
|
int newRecord = Key.GetRecord (row);
|
||
|
// the record did not appeared in the index before update
|
||
|
if (oldRecord == -1 || _size == 0 || !contains) {
|
||
|
if (newRecord >= 0)
|
||
|
if (FindIndexExact (newRecord) < 0)
|
||
|
Add (row,newRecord);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// the record will not appeare in the index after update
|
||
|
if (newRecord < 0 || !Key.CanContain (newRecord)) {
|
||
|
Delete (oldRecord);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
int oldIdx = FindIndexExact (oldRecord);
|
||
|
if (oldIdx == -1) {
|
||
|
Add (row, newRecord);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
int newIdx = -1;
|
||
|
int compare = Key.CompareRecords (_array [oldIdx], newRecord);
|
||
|
int start, end;
|
||
|
|
||
|
int c1 = 1;
|
||
|
int c2 = 1;
|
||
|
|
||
|
if (compare == 0) {
|
||
|
if (_array [oldIdx] == newRecord) {
|
||
|
// we deal with the same record that didn't change
|
||
|
// in the context of current index.
|
||
|
// so , do nothing.
|
||
|
return;
|
||
|
}
|
||
|
} else {
|
||
|
if (know_have_duplicates) {
|
||
|
if (oldIdx > 0)
|
||
|
c1 = Key.CompareRecords (_array [oldIdx - 1], newRecord);
|
||
|
if (oldIdx < _size - 1)
|
||
|
c2 = Key.CompareRecords (_array [oldIdx + 1], newRecord);
|
||
|
|
||
|
if ((c1 == 0 ^ c2 == 0) && compare != 0)
|
||
|
know_have_duplicates = know_no_duplicates = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ((oldIdx == 0 && compare > 0) || (oldIdx == (_size - 1) && compare < 0) || (compare == 0)) {
|
||
|
// no need to switch cells
|
||
|
newIdx = oldIdx;
|
||
|
} else {
|
||
|
if (compare < 0) {
|
||
|
// search after the old place
|
||
|
start = oldIdx + 1;
|
||
|
end = _size - 1;
|
||
|
} else {
|
||
|
// search before the old palce
|
||
|
start = 0;
|
||
|
end = oldIdx - 1;
|
||
|
}
|
||
|
|
||
|
newIdx = LazyBinarySearch (_array, start, end, newRecord);
|
||
|
|
||
|
if (oldIdx < newIdx) {
|
||
|
System.Array.Copy (_array, oldIdx + 1, _array, oldIdx, newIdx - oldIdx);
|
||
|
if (Key.CompareRecords (_array [newIdx], newRecord) > 0)
|
||
|
--newIdx;
|
||
|
} else if (oldIdx > newIdx){
|
||
|
System.Array.Copy (_array, newIdx, _array, newIdx + 1, oldIdx - newIdx);
|
||
|
if (Key.CompareRecords (_array [newIdx], newRecord) < 0)
|
||
|
++newIdx;
|
||
|
}
|
||
|
}
|
||
|
_array[newIdx] = newRecord;
|
||
|
|
||
|
if (compare != 0) {
|
||
|
if (!know_have_duplicates) {
|
||
|
if (newIdx > 0)
|
||
|
c1 = Key.CompareRecords (_array [newIdx - 1], newRecord);
|
||
|
if (newIdx < _size - 1)
|
||
|
c2 = Key.CompareRecords (_array [newIdx + 1], newRecord);
|
||
|
|
||
|
if (c1 == 0 || c2 == 0)
|
||
|
know_have_duplicates = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void Add (DataRow row)
|
||
|
{
|
||
|
Add(row, Key.GetRecord (row));
|
||
|
}
|
||
|
|
||
|
private void Add (DataRow row, int newRecord)
|
||
|
{
|
||
|
int newIdx;
|
||
|
|
||
|
if (newRecord < 0 || !Key.CanContain (newRecord))
|
||
|
return;
|
||
|
|
||
|
if (_size == 0) {
|
||
|
newIdx = 0;
|
||
|
} else {
|
||
|
newIdx = LazyBinarySearch (_array, 0, _size - 1, newRecord);
|
||
|
// if newl value is greater - insert afer old value
|
||
|
// else - insert before old value
|
||
|
if (Key.CompareRecords (_array [newIdx], newRecord) < 0)
|
||
|
newIdx++;
|
||
|
}
|
||
|
|
||
|
Insert (newIdx, newRecord);
|
||
|
|
||
|
int c1 = 1;
|
||
|
int c2 = 1;
|
||
|
if (!know_have_duplicates) {
|
||
|
if (newIdx > 0)
|
||
|
c1 = Key.CompareRecords (_array [newIdx - 1], newRecord);
|
||
|
if (newIdx < _size - 1)
|
||
|
c2 = Key.CompareRecords (_array [newIdx + 1], newRecord);
|
||
|
|
||
|
if (c1 == 0 || c2 == 0)
|
||
|
know_have_duplicates = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void Insert (int index, int r)
|
||
|
{
|
||
|
if (_array.Length == _size) {
|
||
|
int [] tmp = (_size == 0) ? new int [16] : new int [_size << 1];
|
||
|
System.Array.Copy (_array, 0, tmp, 0, index);
|
||
|
tmp [index] = r;
|
||
|
System.Array.Copy (_array, index, tmp, index + 1, _size - index);
|
||
|
_array = tmp;
|
||
|
} else {
|
||
|
System.Array.Copy (_array, index, _array, index + 1, _size - index);
|
||
|
_array [index] = r;
|
||
|
}
|
||
|
_size++;
|
||
|
}
|
||
|
|
||
|
private void MergeSort (int [] to, int length)
|
||
|
{
|
||
|
int [] from = new int [length];
|
||
|
System.Array.Copy (to, 0, from, 0, from.Length);
|
||
|
MergeSort (from, to, 0, from.Length);
|
||
|
}
|
||
|
|
||
|
private void MergeSort (int [] from, int [] to, int p, int r)
|
||
|
{
|
||
|
int q = (p + r) >> 1;
|
||
|
if (q == p)
|
||
|
return;
|
||
|
|
||
|
MergeSort (to, from, p, q);
|
||
|
MergeSort (to, from, q, r);
|
||
|
|
||
|
// merge
|
||
|
for (int middle = q, current = p;;) {
|
||
|
int res = Key.CompareRecords (from[p], from[q]);
|
||
|
if (res > 0) {
|
||
|
to [current++] = from [q++];
|
||
|
|
||
|
if (q == r) {
|
||
|
while (p < middle)
|
||
|
to [current++] = from [p++];
|
||
|
break;
|
||
|
}
|
||
|
} else {
|
||
|
if (res == 0)
|
||
|
know_have_duplicates = true;
|
||
|
|
||
|
to [current++] = from [p++];
|
||
|
|
||
|
if (p == middle) {
|
||
|
while (q < r)
|
||
|
to [current++] = from [q++];
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void QuickSort (int [] a, int p, int r)
|
||
|
{
|
||
|
if (p < r) {
|
||
|
int q = Partition (a, p, r);
|
||
|
QuickSort (a, p, q);
|
||
|
QuickSort (a, q + 1, r);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private int Partition (int [] a, int p, int r)
|
||
|
{
|
||
|
int x = a [p];
|
||
|
int i = p - 1;
|
||
|
int j = r + 1;
|
||
|
|
||
|
while (true) {
|
||
|
// decrement upper limit while values are greater then border value
|
||
|
do {
|
||
|
j--;
|
||
|
} while (Key.CompareRecords (a [j], x) > 0);
|
||
|
|
||
|
do {
|
||
|
i++;
|
||
|
} while (Key.CompareRecords (a [i], x) < 0);
|
||
|
|
||
|
if (i < j) {
|
||
|
int tmp = a [j];
|
||
|
a [j] = a [i];
|
||
|
a [i] = tmp;
|
||
|
} else {
|
||
|
return j;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private int BinarySearch (int [] a, int p, int r, int b)
|
||
|
{
|
||
|
int i = LazyBinarySearch (a, p, r, b);
|
||
|
return (Key.CompareRecords (a [i], b) == 0) ? i : -1;
|
||
|
}
|
||
|
|
||
|
// Lazy binary search only returns the cell number the search finished in,
|
||
|
// but does not checks that the correct value was actually found
|
||
|
private int LazyBinarySearch (int [] a, int p, int r, int b)
|
||
|
{
|
||
|
if (p == r)
|
||
|
return p;
|
||
|
|
||
|
int q = (p + r) >> 1;
|
||
|
|
||
|
int compare = Key.CompareRecords (a [q], b);
|
||
|
if (compare < 0)
|
||
|
return LazyBinarySearch (a, q + 1, r, b);
|
||
|
else if (compare > 0)
|
||
|
return LazyBinarySearch (a, p, q, b);
|
||
|
else
|
||
|
return q;
|
||
|
}
|
||
|
|
||
|
internal void AddRef ()
|
||
|
{
|
||
|
_refCount++;
|
||
|
}
|
||
|
|
||
|
internal void RemoveRef ()
|
||
|
{
|
||
|
_refCount--;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
// Prints indexes. For debugging.
|
||
|
internal void Print ()
|
||
|
{
|
||
|
for (int i=0; i < _size; i++) {
|
||
|
Console.Write ("Index {0} record {1}: ", i, _array [i]);
|
||
|
for (int j=0; j < Key.Table.Columns.Count; j++) {
|
||
|
DataColumn col = Key.Table.Columns [j];
|
||
|
if (_array [i] >= 0)
|
||
|
Console.Write ("{0,15} ", col [_array [i]]);
|
||
|
}
|
||
|
Console.WriteLine ();
|
||
|
}
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
#endregion // Methods
|
||
|
}
|
||
|
}
|