Нашли ошибку или опечатку? Выделите текст и нажмите

Поменять цветовую

гамму сайта?

Поменять
Обновления сайта
и новые разделы

Рекомендовать в Google +1

DataSet

70

Работа с подключенным уровнем позволяет взаимодействовать с базой данных с помощью первичных объектов подключения, команд и чтения данных. Этот небольшой набор типов позволяет выбирать, вставлять, изменять и удалять записи (а также вызывать хранимые процедуры или выполнять другие операции над данными — например, операторы DDL для создания таблицы и DCL для назначения полномочий). Но вы увидели лишь половину ADO.NET, поскольку с помощью объектной модели ADO.NET можно работать и в автономном режиме.

Автономные типы позволяют эмулировать реляционные данные с помощью модели объектов, находящихся в памяти. Кроме простого моделирования табличных данных, состоящих из строк и столбцов, типы из System.Data позволяют воспроизводить отношения между таблицами, ограничения столбцов, первичные ключи, представления и другие примитивы баз данных. К смоделированным данным можно применять фильтры, отправлять запросы и сохранять (или загружать) данные в формате XML и двоичном формате. И все это можно делать, даже не подключаясь к СУБД (откуда и термин "автономный уровень") — достаточно загрузить данные из локального XML-файла или программным образом создать объект DataSet.

Автономные типы действительно можно использовать без подключения к базе данных, но все-таки обычно применяются подключения и объекты команд. Кроме того, используется и особый объект — адаптер данных (расширяющий абстрактный тип DbDataAdapter), который как раз поставляет и обновляет данные. Но в отличие от подключенного уровня, данные, полученные через адаптер данных, не обрабатываются с помощью объектов чтения данных. Вместо этого объекты адаптеров пересылают данные между вызывающим процессом и источником данных с помощью объектов DataSet.

Тип DataSet представляет собой контейнер для любого количества объектов DataTable, каждый из которых содержит коллекцию объектов DataRow и DataColumn. Объект адаптера данных конкретного поставщика данных автоматически обслуживает подключение к базе данных. Для повышения масштабируемости адаптеры данных держат подключение открытым минимально возможное время. Как только вызывающий процесс получит объект DataSet, вызывающий уровень полностью отключается от базы данных и остается с локальной копией удаленных данных.

Теперь в нем можно вставлять, удалять или изменять строки различных объектов DataTable, но физическая база данных не обновляется, пока вызывающий процесс явно не передаст DataSet адаптеру данных для обновления. По сути, объекты DataSet имитируют постоянное подключение клиентов, хотя на самом деле они работают с находящейся в памяти базой данных:

Модель объектов адаптеров данных

Поскольку эпицентром автономного уровня является тип DataSet, то первоочередная задача — научиться вручную оперировать с ним. После этого у вас не будет проблем с обработкой содержимого DataSet, полученного от объекта адаптера данных.

Как уже было сказано, объект DataSet является представлением реляционных данных, находящимся в памяти. Конкретнее, это класс, содержащий внутри себя три внутренних строго типизированных коллекции.

Свойство Tables класса DataSet предоставляет доступ к коллекции DataTableCollection, которая содержит отдельные объекты DataTable.

В DataSet используется еще одна важная коллекция — DataRelationCollection. Поскольку DataSet является автономной версией схемы базы данных, его можно использовать для программного представления отношений родительский/дочерний между ее таблицами. Например, с помощью типа DataRelation можно создать отношение между двумя таблицами, имитирующее ограничение внешнего ключа. Затем с помощью свойства Relations этот объект можно добавить в коллекцию DataRelationCollection. Теперь при поиске данных можно перемещаться по взаимосвязанным таблицам.

Свойство ExtendedProperties предоставляет доступ к объекту PropertyCollection, который позволяет связать с DataSet любую дополнительную информацию в виде пар имя/значение. Эта информация может быть совершенно произвольной, даже не имеющей отношения к самим данным. К примеру, с каким-либо объектом DataSet можно связать название компании, которое будет играть роль находящихся в памяти метаданных. Другими примерами расширенных свойств могут служить временные метки, зашифрованный пароль, который необходим для доступа к содержимому DataSet, число, означающее частоту обновления данных, и многое другое.

Классы DataTable и DataColumn поддерживают также свойство ExtendedProperties.

Прежде чем окунуться в разнообразные программные мелочи, рассмотрим некоторые основные члены класса DataSet. Кроме свойств Tables, Relations и ExtendedProperties, ниже приведено несколько дополнительных полезных свойств:

CaseSensitive

Указывает, чувствительны ли к регистру букв сравнения строк в объектах DataTable. По умолчанию равно false (сравнения строк выполняются без учета регистра букв)

DataSetName

Задает понятное имя для данного DataSet. Обычно это значение передается через параметр конструктора

EnforceConstraints

Задает или получает значение, определяющее, применяются ли правила ограничений при выполнении любых обновлений (по умолчанию равно true)

HasErrors

Получает значение, определяющее, имеются ли ошибки в любой строке любого из объектов DataTable данного DataSet

RemotingFormat

Позволяет определить, как DataSet должен сериализовать свое содержимое (в виде двоичного файла или, по умолчанию, XML)

Методы класса DataSet работают в сочетании с некоторыми функциями, которые обеспечивают описанные выше свойства. Кроме взаимодействия с потоками XML, DataSet содержит методы, позволяющие копировать содержимое DataSet, перемещаться между внутренними таблицами и устанавливать начальные и конечные точки пакетных обновлений:

AcceptChanges()

Отправляет все изменения, выполненные в данном DataSet после его загрузки или последнего вызова AcceptChanges()

Clear()

Полностью очищает DataSet, удаляя все строки в каждом DataTable

Clone()

Клонирует структуру DataSet, в том числе и всех DataTable, а также все отношения и ограничения

Copy()

Копирует структуру и данные текущего DataSet

GetChanges()

Возвращает копию DataSet, содержащую все изменения, которые были выполнены в данном DataSet после его загрузки или последнего вызова AcceptChanges(). У этого метода есть перегруженные варианты, которые позволяют получить только новые строки, только измененные строки или только удаленные строки

HasChanges()

Выдает, содержит ли DataSet изменения, т.е. новые, удаленные или измененные строки

Merge()

Объединяет данный DataSet с указанным DataSet

ReadXml()

Позволяет определить структуру объекта DataSet и заполнить его данными на основе XML-схемы и данных из потока

RejectChanges()

Отменяет все изменения, которые были выполнены в данном DataSet после его загрузки или последнего вызова AcceptChanges()

WriteXml()

Позволяет записать содержимое DataSet в поток

Теперь, когда вы уже лучше понимаете роль DataSet (и имеете некоторое представление о его возможностях), создайте новое консольное приложение по имени SimpleDataSet и импортируйте пространство имен System.Data. В методе Main() определите новый объект DataSet с тремя расширенными свойствами, представляющими временную метку, уникальный идентификатор (типа System.Guid) и название компании:

static void Main(string[] args)
{
            // Создание DataSet
            DataSet carsInventoryDS = new DataSet("Car Inventory");

            carsInventoryDS.ExtendedProperties["TimeStamp"] = DateTime.Now;
            carsInventoryDS.ExtendedProperties["DataSetID"] = Guid.NewGuid();
            carsInventoryDS.ExtendedProperties["Company"] = "Мой магазин";
            Console.ReadLine();
}

Если вы не знакомы с концепцией глобально уникальных идентификаторов (globally unique identifier — GUID), просто считайте, что это статически уникальное 128-битное число. Хотя идентификаторы GUID применяются в среде СОМ для идентификации различных сущностей СОМ (классы, интерфейсы, приложения и т.д.), тип System.Guid очень полезен и в .NET, когда нужно быстро сгенерировать уникальный идентификатор.

В любом случае объект DataSet не очень-то интересен, если он не содержит хоть немного объектов DataTable. Значит, теперь нужно изучить внутреннее устройство класса DataTable, начиная с типа DataColumn.

Пройди тесты