DataTable
32Работа с базами данных в .NET Framework --- ADO.NET --- DataTable
Тип DataTable определяет значительное количество членов, многие из которых совпадают по именам и функциям с аналогичными членами DataSet. Ниже приведены некоторые основные члены типа DataTable, кроме Rows и Columns:
- CaseSensitive
Указывает, чувствительны ли к регистру символов строковые сравнения в таблице. По умолчанию равно false
- ChildRelations
Возвращает коллекцию дочерних отношений для данного DataTable (если они есть)
- Constraints
Получает коллекцию ограничений, поддерживаемых данной таблицей
- Copy()
Метод, копирующий схему и данные DataTable в новый экземпляр
- DataSet
Получает DataSet, содержащий данную таблицу (если он есть)
- DefaultView
Получает специализированное представление таблицы, которое может содержать отфильтрованное представление или позицию курсора
- ParentRelations
Получает коллекцию родительских отношений для данного DataTable
- PrimaryKey
Получает или задает массив столбцов, которые выступают в качестве первичных ключей для таблицы данных
- RemotingFormat
Позволяет определить формат сериализации объектом DataSet его содержимого (двоичный или XML) для уровня .NET Remoting
- TableName
Получает или задает имя таблицы. Значение этого свойства можно также задать через параметр конструктора
В продолжение нашего примера занесем в свойство PrimaryKey объекта DataTable объект DataColumn по имени carIDColumn. Учтите, что свойству PrimaryKey соответствует коллекция объектов DataColumn, чтобы можно было обрабатывать ключи из нескольких столбцов. Но в нашем случае нужно указать только столбец CarID (который находится в таблице в самой первой позиции):
// Первичный ключ для таблицы
inventoryTable.PrimaryKey = new DataColumn[] { inventoryTable.Columns[0] };
// Добавление таблицы в DataSet
ds.Tables.Add(inventoryTable);
Теперь нужно вставить в метод Main() вызов FillDataSet() и передать ему в качестве аргумента локальный объект DataSet. Затем передадим этот объект новому вспомогательному методу PrintDataSet (Метод PrintDataSet() просто перебирает все метаданные DataSet (используя коллекцию ExtendedProperties) и все DataTable в этом DataSet, выводя имена столбцов и значения строк с помощью индексаторов):
static void Main(string[] args)
{
// Создание DataSet
DataSet carsInvenoryDS = new DataSet("Car Inventory");
carsInvenoryDS.ExtendedProperties["TimeStamp"] = DateTime.Now;
carsInvenoryDS.ExtendedProperties["DataSetID"] = Guid.NewGuid();
carsInvenoryDS.ExtendedProperties["Company"] = "Мой магазин";
FillDataSet(carsInvenoryDS);
PrintDataSet(carsInvenoryDS);
Console.ReadLine();
}
static void PrintDataSet(DataSet ds)
{
// Вывод имени и расширенных свойств
Console.WriteLine("*** Объекты DataSet ***\n");
Console.WriteLine("Имя DataSet: {0}", ds.DataSetName);
foreach (System.Collections.DictionaryEntry de in ds.ExtendedProperties)
Console.WriteLine("Ключ = {0}, Значение = {1}", de.Key, de.Value);
Console.WriteLine();
// Вывод каждой таблицы
foreach (DataTable dt in ds.Tables)
{
Console.WriteLine("=> Таблица: {0}", dt.TableName);
// Вывод имени столбцов
for (int curCol = 0; curCol < dt.Columns.Count; curCol++)
Console.Write(dt.Columns[curCol].ColumnName + "\t");
Console.WriteLine("\n--------------------------");
// Выводим содержимое таблицы
for (int curRow = 0; curRow < dt.Rows.Count; curRow++)
for (int curCol = 0; curCol < dt.Columns.Count; curCol++)
Console.WriteLine(dt.Rows[curRow][curCol].ToString() + "\t");
Console.WriteLine();
}
}
Если теперь запустить эту программу, буде получен следующий результат (конечно, с другими отметками времени и значением GUID):

Обработка данных из DataTable с помощью объектов DataTableReader
Вспомните вашу работу в предыдущем примере, и вы поймете, что способы обработки данных с помощью подключенного уровня (т.е. с помощью объектов чтения данных) и автономного уровня (т.е. с помощью объектов DataSet) весьма различаются. При работе с объектом чтения данных обычно пишется цикл while, вызывается метод Read(), и с помощью индексатора выбираются пары имя/значение. А при обработке DataSet нужен целый ряд циклических конструкций, чтобы добраться до данных, находящихся в таблицах, строках и столбцах (не забывайте, что для DataReader нужно открытое подключение к базе данных, чтобы он мог прочитать данные из реальной базы).
Объекты DataTable поддерживают метод CreateDataReader(). Этот метод позволяет получать данные из DataTable с помощью схемы навигации, похожей на тип чтения данных (объект чтения данных читает данные из находящейся в памяти таблицы DataTable, а не из реальной базы данных, поэтому здесь подключение к базе данных не требуется). Основное преимущество такого подхода состоит в том, что теперь при обработке данных используется единая модель, независимо от уровня ADO.NET, применяемого для получения этих данных. Допустим, в класс Program добавлена следующая вспомогательная функция по имени PrintTable():
static void PrintTable(DataTable dt)
{
// Создание объекта DataTableReader
DataTableReader dtReader = dt.CreateDataReader();
while (dtReader.Read())
{
for (int i = 0; i < dtReader.FieldCount; i++)
Console.Write("{0}\t",dtReader.GetValue(i).ToString().Trim());
Console.WriteLine();
}
dtReader.Close();
}
Тип DataTableReader работает точно так же, как и объект чтения данных конкретного поставщика данных. Он очень удобен, если нужно быстро загрузить данными объект DataTable, не путаясь во внутренних коллекциях строк и столбцов. А теперь изменим предыдущий метод PrintDataSet(), чтобы в нем применялись вызовы PrintTable(), а не перебор коллекций Rows и Columns:
static void PrintDataSet(DataSet ds)
{
// Вывод имени и расширенных свойств
Console.WriteLine("*** Объекты DataSet ***\n");
Console.WriteLine("Имя DataSet: {0}", ds.DataSetName);
foreach (System.Collections.DictionaryEntry de in ds.ExtendedProperties)
Console.WriteLine("Ключ = {0}, Значение = {1}", de.Key, de.Value);
Console.WriteLine();
// Вывод каждой таблицы
foreach (DataTable dt in ds.Tables)
{
Console.WriteLine("=> Таблица: {0}", dt.TableName);
// Вывод имени столбцов
for (int curCol = 0; curCol < dt.Columns.Count; curCol++)
Console.Write(dt.Columns[curCol].ColumnName + "\t");
Console.WriteLine("\n--------------------------");
// Выводим содержимое таблицы
PrintTable(dt);
}
}
После запуска этого приложения вы увидите выходные данные, полностью совпадающие с приведенными на рисунке выше. Единственным отличием будет внутренний доступ к содержимому DataTable.