Знакомство с Microsoft .NET Framework 2.0

Часть 4. ADO .NET 2.0

Алексей Федоров

Общие изменения

   Пространство имен System.Data

   Пространства имен System.Data.Common и System.Data.ProviderBase

Изменения, специфические для SQL Server

Изменения, специфические для SQL Server 2005

 

Об авторе. Алексей Федоров — сотрудник отдела стратегических технологий российского представительства компании Microsoft (alexeif@microsoft.com).

Мы продолжаем рассказ об основных изменениях, появившихся в Microsoft .NET Framework 2.0. В предыдущих разделах (см. КомпьютерПресс № 10, 12’2004, 1’2005) мы рассмотрели общие вопросы, а также новшества в технологиях создания Windows-приложений (Windows Forms 2.0) и Web-приложений (ASP .NET 2.0). На очереди — технология доступа к данным ADO .NET 2.0, которой и посвящена данная статья.

Технология ADO .NET уходит корнями в ODBC, DAO, RDO, ADO и OLEDB. Некоторые из этих механизмов в том или ином виде существуют в .NET Framework, но разработчики, создающие управляемый код, чаще всего для доступа к различным источникам данных используют ADO .NET. В версии 2.0 этой технологии появился ряд изменений, вызванных в первую очередь необходимостью повышения производительности механизмов работы с данными. Помимо этого ряд новых классов в ADO .NET 2.0 предоставляет доступ к функциям SQL Server 2005.

Технология ADO .NET 2.0 доступна в виде ряда пространств имен, физически реализованных в библиотеке System.Data.dll (за исключением клиента Oracle, реализованного в отдельной библиотеке System.Data.OracleClient.dll). Пространства имен, относящиеся к ADO .NET 2.0, показаны в табл. 1.

 

Таблица 1. Пространства имен, относящиеся к ADO .NET 2.0

Таблица 1. Пространства имен, относящиеся к ADO .NET 2.0

Теперь, после того как читатели составили общее представление о структуре ADO .NET 2.0, следует более подробно рассмотреть появившиеся в этой технологии изменения и дополнения. Начнем с изменений общего характера, а затем обратимся к поддержке функциональности, уникальной для новой версии СУБД Microsoft — SQL Server 2005.

Общие изменения

Как мы уже отмечали, большинство изменений в ADO .NET 2.0 связано с необходимостью увеличения производительности механизмов доступа к данным.

Пространство имен System.Data

У класса DataSet появилось новое свойство RemotingFormat, позволяющее указать способ сериализации — XML или бинарный (binary) — и в случае выбора последнего существенно сократить трафик при передаче наборов данных между процессами при использовании технологии .NET Remoting.

Для упрощения сериализации наборов данных (DataSet) и снижения объема передаваемых данных у класса DataTable появились методы ReadXml, WriteXml и ReadXmlSchema, позволяющие сериализовать таблицу без необходимости сериализации содержащего ее набора данных, а также новое свойство RemotingFormat, позволяющее указать способ сериализации.

На уровне записей появилась возможность программного изменения их состояния (свойство RowState класса DataRow) с помощью методов SetAdded и SetModified. Использование этих методов приводит к принудительному обновлению данных, даже если сами данные не претерпели изменений.

К другим изменениям можно отнести появление нового класса DataTableReader, который возвращает экземпляр класса DataTable на основе существующего класса DataReader с помощью метода DataTable.Load (DataReader). При этом можно указать (через параметр LoadOption метода Load), как поступать с существующими в таблице данными — перезаписать их (OverwriteRow), сохранить (PreserveCurrentValues) или обновить (UpdateCurrentValues). Также отметим ряд дополнительных исключений, описанных в пространстве имен System.Data, таких как AdapterMappingException, DataAdapterException, OperationAbortedException, и ряд новых событий и соответствующих им обработчиков: DataTableClearEventArgs, DataTableClearEventHandler; DataTableNewRowEventArgs, DataTableNewRowEventHandler; StatementCompletedEventArgs и StatementCompletedEventHandler.

Пространства имен System.Data.Common и System.Data.ProviderBase

Теперь перейдем к изменениям в пространствах имен System.Data.Common и System.Data.ProviderBase. Здесь мы обнаружим основные принципиальные изменения, произведенные в ADO .NET 2.0 и связанные с моделью реализации провайдеров для доступа к источникам данных.

В пространстве имен System.Data. Common находятся базовые классы, используемые провайдерами данных. Многие из этих классов имеют атрибут must inherit и обеспечивают поддержку новой модели абстрактных провайдеров, не зависящих от конкретных источников данных. (Напомним, что в ADO .NET 1.x использовалась модель провайдеров на основе интерфейсов, вследствие чего создание собственных провайдеров было достаточно сложной задачей.) Использование абстрактных базовых классов в версии 2.0, а также вспомогательных классов из пространства имен System.Data.ProviderBase облегчает процесс создания провайдеров и позволяет управлять соединениями и командами в режиме исполнения. Данная функциональность реализована на основе шаблона factory (класс DbProviderFactory), который возвращает конкретный тип провайдера по указанному имени, например System.Data.SqlClient. Такой подход необходим в тех случаях, когда источник данных может измениться уже после создания приложения. Если же приложение ориентируется на применение заранее известного источника данных, следует использовать пространства имен и классы, оптимизированные для данного типа источника данных, например System.Data.SqlClient.

В табл. 2 представлены новые классы, реализованные в пространстве имен System.Data.Common.

 

Таблица 2. Классы, реализованные в пространстве имен System.Data.Common

Таблица 2. Классы, реализованные в пространстве имен System.Data.Common

Классы DbMetaDataXXX обеспечивают поддержку получения метаданных, реализованную на уровне метода GetSchema класса DbConnection. При вызове метода указываются название коллекции метаданных (CollectionName) и возможный уровень ограничений (Restrictions). Общие названия коллекций и уровни ограничений приведены в табл. 3.

 

Таблица 3. Общие названия коллекций метаданных и уровни ограничений

Таблица 3. Общие названия коллекций метаданных и уровни ограничений

Метод GetSchema возвращает таблицу (System.Data.DataTable), заполненную метаданными, соответствующими заданной коллекции.

Также реализована поддержка программного получения списка доступных провайдеров (с помощью метода DbProviderFactories.GetFactoryClasses), которая в первую очередь должна быть интересна разработчикам различных утилит. Информация о доступных провайдерах хранится в конфигурационном файле machine.config и возвращается методом GetFactoryClasses в виде таблицы System.Data.DataTable, состоящей из пяти полей: название провайдера; описание; имя провайдера, которое можно использовать для его программного создания; полное имя сборки, в которой реализован данный провайдер; число поддерживаемых классов (DBProviderSupportedClasses).

В табл. 4 показаны классы, реализованные в пространстве имен System.Data.ProviderBase.

 

Таблица 4. Классы, реализованные в пространстве имен System.Data.ProviderBase

Таблица 4. Классы, реализованные в пространстве имен System.Data.ProviderBase

В ADO .NET 1.x обновления происходили одно за другим — обновление каждой записи рассматривалось как отдельная «команда». В версии 2.0 DataAdapter и DataSet позволяют выполнить пакетное обновление для тех источников данных, которые поддерживают данную функциональность. Свойство UpdateBatchSize класса DbDataAdapter (и классов на его основе — SqlDataAdapter и OracleDataAdapter) позволяет включить пакетное обновление и задать размер очереди.

В начало В начало

Изменения, специфические для SQL Server

Среди новинок, специфических для SQL Server, следует отметить поддержку асинхронных команд и массовое копирование (bulk copy).

В пространстве имен System.Data. SqlClient реализован ряд новых методов класса SqlCommand, позволяющих выполнять асинхронные операции. Для ряда методов, таких как ExecuteNonQuery, ExecuteReader и ExecuteXmlReader, появились парные асинхронные методы Begin и End, как показано в табл. 5.

 

Таблица 5. Новые методы

Таблица 5. Новые методы

Использование асинхронных команд может быть полезно в тех случаях, когда необходимо выполнение нескольких операций или хранимых процедур. Возможно использование асинхронных команд в трех различных сценариях — Polling, Wait и Callback:

  • в первом случае (Polling) используется синтаксическая конструкция while для выполнения кода в процессе ожидания изменения значения флага IsCompleted;
  • в случае сценария Wait используются класс WaitHandle и метод WaitAll для ожидания завершения всех команд или метод WaitAny для ожидания завершения каждой отдельной команды;
  • в сценарии Callback создается косвенно-вызываемая процедура (callback), которая получает управление по завершении выполнения асинхронной команды.

В любом случае для использования асинхронных команд необходимо указать в строке соединения параметр «async=true».

При использовании асинхронных команд необходимо помнить о многопоточности и возможных нагрузках при переключении между потоками. Также нельзя забывать, что многопоточная поддержка на уровне .NET не гарантирует, что операция, начатая в одном потоке, именно в нем и завершится.

Еще одна новация связана с массовым копированием. В ряде случаев требуется быстрый ввод в базу данных больших массивов данных с помощью команды INSERT. Обычно такие данные располагаются в файлах или могут поступать с различных устройств. Новый класс пространства имен System.Data.SqlClient — SqlBulkCopy — обеспечивает быструю и эффективную загрузку данных. Данные могут поступать из наборов данных (DataSet) или из классов типа DataReader, что означает, что данные можно извлекать как из источников данных, так и из других источников: файлов, устройств и т.п. При необходимости изменения структуры данных применяется свойство ColumnMappings. Для получения нотификаций в процессе массового копирования можно использовать свойство NotifyAfter и обработчик события SqlRowsCopied.

И еще одно новшество — поддержка параметра строки соединения AttachDbFileName, используемого для подключения к MSDE и SQL Server 2005 Express Edition на уровне файла конфигурации с возможностью указания относительного расположения файла базы данных.

В начало В начало

Изменения, специфические для SQL Server 2005

Следующая группа новаций относится к поддержке функциональности в новой версии SQL Server — к SQL Server 2005. Здесь мы найдем возможность получения нескольких активных наборов данных по одному соединению (Multiple Active Resultsets, MARS), поддержку получения нотификаций от SQL Server, возможность программного изменения пароля, интеграцию с транзакционной системой на уровне System.Transactions, поддержку новых для SQL Server 2005 типов данных и пр. Ниже мы рассмотрим основные из этих возможностей более подробно.

Возможность получения нескольких активных наборов данных по одному соединению позволяет использовать более одного экземпляра SqlDataReader, открытого для данного соединения, если каждый экземпляр SqlDataReader был открыт по отдельной команде. Примером применения этой функциональности может быть выполнение нескольких методов ExecuteNonQuery при открытом экземпляре DataReader. Используя MARS, можно выполнять следующие сценарии:

  • получение списка клиентов и перемещение по списку;
  • получение списка заказов для каждого клиента;
  • получение списка продуктов для каждого заказа.

Использование MARS происходит автоматически, не требуя никаких дополнительных конфигураций или написания дополнительного кода. Единственное, что необходимо помнить, — это то, что все экземпляры SqlDataReader обращаются к единой базе данных с одинаковыми настройками безопасности. Кроме того, все операции должны происходить в рамках одной транзакции (SqlTransaction), которая ассоциируется с командой (SqlCommand) через свойство SqlCommand.Transaction. По умолчанию MARS поддерживается только для SQL Server 2005. Для отключения этой возможности следует указать в строке соединения параметр «MultipleActiveResultSets=false».

Два новых класса — SqlNotificationRequest и SqlDependency — позволяют получать уведомления от базы данных о произошедших изменениях. Класс SqlDependency служит высокоуровневой оболочкой для SqlNotificationRequest и возвращает уведомление в виде стандартного события, тогда как непосредственное использование класса SqlNotificationRequest требует написания дополнительного кода. В SQL Server 2005 возможность получения уведомлений реализована на основе SQL Server Service Broker.

В SQL Server 2005 появилась возможность задавать политику изменения паролей, как и при использовании Windows-логинов. Для этого требуется, чтобы сервер SQL Server 2005 работал под управлением Windows Server 2003. Если SQL-логин устарел, то невозможно использовать традиционные механизмы Windows и API для его обновления и изменения. Единственный способ изменить логин в этом случае — применить команды TSQL ALTER LOGIN. В классе SqlConnection появился новый метод ChangePassword, позволяющий изменить логин на стороне клиента. Это означает, что логин и пароль больше не должны храниться в строке соединения — их следует располагать в зашифрованном виде в конфигурационном файле. Впрочем, многие разработчики уже давно используют такой подход.

Следующее новшество связано с интеграцией с транзакционной системой на уровне System.Transactions. Напомним, что средства TSQL позволяют начать локальную или распределенную транзакцию (BEGIN TRANSACTION и BEGIN DISTRIBUTED TRANSACTION), но иногда возникают ситуации, когда требуется поддержка нескольких экземпляров SQL Server и автоматического преобразования локальных транзакций в распределенные. Интеграция SqlClient с System.Transactions дает возможность программно осуществлять такие операции даже с различными типами баз данных в том случае, если первая база управляется с помощью SQL Server.

В SQL Server 2005 появилась поддержка изоляции транзакций через новые методы, а также поддержка блокировок и версионности (в предыдущих версиях SQL Server существовала поддержка блокировок, но поддержка версионности отсутствовала). Поддерживается версионность двух типов — на уровне команд (statement-level versioning) и на уровне транзакций (transaction-level versioning). По умолчанию используется версионность на уровне команд. В SQL Server поддерживаются все четыре уровня изоляции транзакций на уровне спецификации ANSI SQL (READ UNCOMMITED, READ COMMITTED, REPEATABLE READ и SERIALIZABLE). В SQL Server 2005 появился и новый уровень изоляции — IsolationLevel.Snapshot, поддерживаемый только на уровне SqlClient.

Последняя новация, которую мы рассмотрим, относится к поддержке новых для SQL Server 2005 типов данных. В SQL Server 2005 появилась возможность создания собственных типов данных (user-defined types) и типа данных XML, а также улучшенная поддержка данных большого объема. Данные большого типа поддерживаются на уровне типов VARCHAR(MAX), NVARCHAR(MAX) и VARBINARY(MAX). Пользовательские типы данных и тип данных XML реализованы через новые классы в пространстве имен System.Data.SqlTypes — SqlUdt и SqlXml соответственно. Для их использования в перечисление SqlDbTypes добавлены новые типы; метод IDataReader.GetValue позволяет возвращать пользовательские типы как объекты .NET, а XML-данные как строки.

Новые для SQL Server 2005 типы поддерживаются на уровне DataReader — при использовании команд SQL SELECT и как параметры при применении SqlParameter. Класс SqlMetaData позволяет получить информацию о расширенных свойствах новых типов данных, например о схеме для XML-данных или от имени базы данных для пользовательского типа.

В табл. 6 показаны новые классы в пространстве имен System.Data.Sql, а новые классы в пространстве имен System.Data.SqlClient — в табл. 7.

 

Таблица 6. Новые классы в пространстве имен System.Data.Sql

Таблица 6. Новые классы в пространстве имен System.Data.Sql

Таблица 7. Новые классы в пространстве имен System.Data.SqlClient

Таблица 7. Новые классы в пространстве имен System.Data.SqlClient

На этом мы завершаем наше краткое знакомство с новинками, появившимися в технологии доступа к данным ADO .NET 2. 0. В следующий раз мы рассмотрим основные изменения, произведенные в технологиях работы с XML-документами и в технологиях создания и использования Web-сервисов.

КомпьютерПресс 3'2005