Кроме этого обратите внимание на то, что вызов BeginExecuteDataReader() возвращает ожидаемый IAsyncResult-совместимый тип, который используется для синхронизации потока вызова (с помощью свойства IsCompleted), а также для получения SqlDataReader по завершении выполнения запроса.
Исходный код. Проект AsyncCmdObject размещен в подкаталоге, соответствующем главе22.
Несвязный уровень ADO.NET
Как вы убедились, работе, со связным слоем позволяет взаимодействовать с базой данных, используя объекты соединения, команд и чтения данных. С помощью небольшого набора типов вы можете по желанию выбирать, вставлять, обновлять и удалять записи (а также запускать хранимые процедуры). Но на самом деле вы пока что узнали только половину того, что вам следует знать о возможностях ADO.NET. Поэтому напоминаем, что объектная модель ADO.NET может использоваться для взаимодействия в несвязной форме.
При работе на несвязном уровне ADO.NET вы по-прежнему должны использовать объекты соединения и команды. Кроме того, вы должны использовать специальный объект, называемый адаптером данных (и расширяющий абстрактный DbDataAdapter), чтобы извлекать и обновлять данные. В отличие от связного слоя, данные, полученные с помощью адаптера данных, не обрабатываются с помощью объекта чтения данных. Вместо этого для перемещения данных между вызывающей стороной и источником данных объекты адаптера данных используют объекты DataSet. Тип DataSet – это контейнер, используемый для любого числа объектов DataTable, каждый из которых содержит коллекцию объектов DataRow и DataColumn.
Объект адаптера данных вашего поставщика данных обрабатывает соединение с базой данных автоматически. С целью расширения возможностей масштабируемости адаптеры данных сохраняют соединение открытым минимально возможное время. Как только вызывающая сторона получает объект DataSet, соединение с СУБД разрывается, и вызывающая сторона остается со своей локальной копией удаленных данных. Вызывающая сторона может вставлять, удалять и модифицировать данные DataTable, но физически база данных не будет обновлена до тех пор. пока вызывающая сторона не передаст явно объект DataSet адаптеру данных для обновления. В сущности, DataSet позволяет клиенту имитировать постоянно открытое соединение, в то время как реальные операции выполняются с наборами данных, находящимися в памяти (рис. 22.10).
Рис. 22.10. Объекты адаптера данных передают объекты DataSet клиенту и возвращают их обратно базе данных
Поскольку основным элементом несвязного уровня является тип DataSet, нашей следующей задачей будет выяснение того, как управлять объектом DataSet вручную. Если вы поймете, как это делается, то не будете испытывать никаких проблем При манипуляциях содержимым DataSet, извлеченным из объекта адаптера данных.
Упрощенно говоря, DataSet является представлением внешних данных в памяти. Более точно, DataSet представляет собой тип класса, поддерживающий три внутренние строго типизованные коллекции (рис. 22.11).
Рис. 22.11. "Анатомия" DataSet
Свойство Tables объекта DataSet позволяет получить доступ к коллекции DataTableCollection, содержащей отдельные объекты DataTable. Другой важной коллекцией DataSet является DataRelationCollection. Ввиду того, что объект DataSet является "отсоединенным" образом структуры базы данных, можно программно представлять родительски-наследственные связи между таблицами. Например, с помощью типа DataRelation можно создать отношение между двумя таблицами, моделирующее ограничение внешнего ключа, Соответствующий объект можно затем добавить в DataRelationCollection с помощью свойства Relations. После этого вы сможете осуществлять переходы между соединенными таблицами при поиске данных. Как это реализуется на практике, будет доказано немного позже.
Свойство ExtendedProperties обеспечивает доступ к объекту Property-Collection, который позволяет ассоциировать с DataSet любую дополнительную информацию, используя пары имен и значений. Эта информация может быть практически любой, и даже вообще не иметь никакого отношений к данным. Например, можно связать с DataSet название вашей компании, которое в этом случае может выступать в роли включенных в память метаданных. Другими примерами таких расширенных свойств могут быть штамп даты/времени, шифрованный пароль, который необходимо будет указать для доступа к содержимому DataSet, число, задающее частоту обновления данных, и т.д.
Читать дальше