DataTable

32

Тип 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):

Получение данных из DataSet

Обработка данных из 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.

Пройди тесты
Лучший чат для C# программистов