Тема 1. «Новейшие направления в области создания технологий программирования» Цель Рассмотреть историю и подробности реализации доступа к данным. Задачи 1. Познакомиться с законами эволюции программного обеспечения. 2. Рассмотреть базовые понятия современной технологии доступа к данным ADO.NET. 3. Выполнить подробное знакомство с пространством имен System.Data. 4. Изучить механизмы извлечения данных из хранилищ с помощью управляемых провайдеров. Оглавление Законы эволюции программного обеспечения ADO.NET – новая стратегия доступа к данным Управляемые провайдеры данных Пространства имен, используемые для доступа к данным Механизмы извлечения данных из хранилищ с помощью управляемого провайдера Выводы Вопросы для самопроверки Литература Законы эволюции программного обеспечения Сегодня любое приложение каким-либо образом связано с обращением к данным. При использовании настольных приложений, предназначенных для работы на компьютерах, функционирующих вне сети, доступ к данным осуществляется сравнительно просто, поскольку эти данные хранятся локально. С другой стороны, распределенные приложения работают с удаленными источниками информации, содержащими данные различных форматов, способы хранения которых, могут отличаться. Поэтому обращение к данным в распределенных приложениях организовать сложнее, чем в настольных приложениях. Для получения информации из различных источников необходимо создавать и использовать приложения доступа к данным. Начнем наш экскурс в мир приложений баз данных Visual Basic.NET с обзора существующих на сегодняшний день методологий доступа к данным: ADO и ADO.NET. В истории универсального доступа к данным и объектам данных ActiveX (ActiveX Data Object – активные объекты данных) технология ADO является предшественником технологии ADO.NET. В свое время ADO пришла на смену технологии объектов доступа к данным (Data Access Object – DAO) и удаленным объектам данных (Remote Data Objects – RDO), предложив более мощные средства извлечения и управления данными. Технологии DAO и RDO изначально были предназначены для использования в клиент-серверных приложениях и действительно отлично подходили для этих целей. На рис. 1.1 изображены традиционные методы доступа к данным Microsoft. Application DAO Объекты доступа к данным RDO Удаленное управление данными ODBC Открытый интерфейс доступа к базам данных Jet data source Встроенные процессоры баз данных Реляционные базы данных Нереляционные источники данных (файловые системы, почтовые сервера и другие) Рис. 1.1. Методы доступа к данным Microsoft (традиционные) Однако, по мере развития технологий распределенных вычислений с многоуровневой архитектурой, а также увеличения размеров и широкого распространения различных типов хранилищ данных, возникла необходимость в боле сложных способах доступа и обработки данных на множестве имеющихся платформ и источников данных. Рис. 1.2 иллюстрирует более современную модель доступа к данным. Application ADO OLE DB ODBC Открытый интерфейс доступа к базам данных Нереляционные источники данных (файловые системы, почтовые сервера и другие) Реляционные базы данных Jet data source Встроенные процессоры баз данных Рис. 1.2. Развитие методов доступа к данным Microsoft Решать возникшую проблему была призвана технология OLE DB, в результате чего именно интерфейс ADO стал использоваться для доступа к источникам данных OLE DB из пользовательских приложений. OLE DB представляет собой реализованную компанией Microsoft методологию универсального доступа к данным, независимую от места хранения самих данных: будь то реляционная база данных, файловая система, почтовый сервер или что-то другое. Объектная модель ADO состоит из следующих основных объектов: Connection (подключение) – позволяет устанавливать подключение к источникам данных; Command (команда) – дает возможность отправлять команды, которые должны быть применены к источнику данных; RecordSet (набор записей) – главный объект модели, который предоставляет основные возможности по извлечению и сохранению данных в виде однородной таблицы. Интерфейс ADO надежен, благодаря чему он превратился в стандартную технологию доступа из приложений. Хотя появление ADO стало важным шагом, послужившим толчком к развитию других технологий доступа к данным, ADO также обладает рядом недостатков, например: Объект ADO RecordSet имеет вид однородной таблицы, не поддерживает отношений между таблицами. Объект RecordSet обычно применяется в режиме активного подключения, что приводит к увеличению числа блокировок в базе данных. ADO.NET – новая стратегия доступа к данным ADO.NET представляет собой не просто усовершенствованную версию интерфейса, скорее ADO.NET – новая стратегия доступа к данным. Основная идея состоит в том, что в сегодняшнем мире, для которого характерен высокий уровень информационной интеграции, ваше приложение может использовать данные из множества источников, хранимые в различных форматах. В этой ситуации, получив требуемую информацию через сеть за достаточно короткий промежуток времени, дальнейшую обработку можно выполнять локально, без необходимости постоянно поддерживать соединение с хранилищами данных. Все внесенные изменения могут быть отправлены для сохранения в источники позднее, тогда, когда это будет удобно для вас. В этом состоит концептуальное отличие подхода ADO.NET от всех его предшественников, поддерживающих активное соединение с базовыми хранилищами данных, пока данные находятся в обработке. ADO.NET представляет первичные средства доступа к данным: через объекты DataReader и DataSet. Объект DataReader предназначен исключительно для последовательного считывания информации, и поэтому используется для быстрого и эффективного доступа к потоковым данным. Объект DataSet представляет собой копию данных, размещенных в памяти. Рассмотрим подробнее место этих объектов в архитектуре ADO.NET (рис. 1.3). Объект DataReader работает в режиме активного подключения и позволяет выполнять только последовательное извлечение из хранилища данных, доступных только для чтения. Подключение к базе данных остается открытым, пока вы работаете с объектом DataReader, и должно быть закрыто, когда работа с ним будет завершена. Объект DataReader изначально был создан для максимально быстрого доступа к информации, которая после извлечения должна выводиться на экран, после этого соединение может быть разорвано. Соответственно, объект не предназначен для навигации по результирующему множеству в произвольном направлении или модификации данных. Данный объект обладает наибольшим сходством с объектом последовательного чтения RecordSet в ADO. Уровень пользовательского интерфейса XML Промежуточный уровень Уровень данных DataReader DataAdapter Хранилище данных Command DataSet Хранилище данных Connection Рис. 1.3. Архитектура ADO.NET Объект DataSet можно считать главным объектом в ADO.NET. В отличие от объекта ADO RecordSet, он может содержать несколько таблиц, извлеченных из различных источников данных. Таблицы в объекте DataSet могут быть связаны между собой отношениями. По сути, объект DataSet является временной базой данных, хранимой в памяти, которая не связана активными подключениями с источниками данных. Управляемые провайдеры данных В мире приложений баз данных .NET существуют провайдеры данных и их потребители. Провайдеры данных (data providers) подключаются к базе данных для выполнения команд и получения возвращаемых результатов. В ADO.NET провайдеры данных называются управляемыми провайдерами (managed providers), поскольку управление этими провайдерами осуществляется ядром ADO.NET. Потребителями данных (data consumers) выступают те приложения, которые используют службы провайдеров данных для извлечения и обработки данных. Как правило, провайдер данных включает в себя следующие объекты: Connection, Command, DataAdapter и DataReader (рис. 1.4). Приложение Data Set .NETпровайдер= Data Adapter+ Connection+ Command+ Data Reader База данных Рис. 1.4. Компоненты управляемого провайдера данных На рис. 1.5 подробнее поясняется механизм доступа к данным. Обратите внимание на то, что существуют два различных способа доступа к данным со стороны клиента: через DataSet и через DataReader. В случае использования DataSet, подключение к базе данных открывается, и DataAdapter отправляет команды (Command) через объект Connection для извлечения данных из хранилища. Затем DataAdapter заполняет объект DataSet извлеченными значениями и возвращает его клиенту. На самом деле, для загрузки данных в DataSet ADO.NET скрытым образом использует объект DataReader. Это не показано на рис. 1.3 и 1.5, так как, во-первых, это скрытый механизм, выполняемый ADO.NET без вашего участия, во-вторых, приведенные рисунки демонстрируют различие двух методов доступа: с помощью DataReader и DataSet. DataTable DataColumn DataTable Constraint DataColumn DataRow DataRelation Constraint DataRow DataSet DataReader DataAdapter Провайдер данных Command Хранилище данных Connection Рис. 1.5. Работа управляемого провайдера данных При использовании DataReader открывается подключение к базе данных, DataReader отсылает команды Command через объект Connection для получения потоковых данных. Обратите внимание, что двунаправленная стрелка между объектами DataReader и Command просто означает выполнение объекта Command для извлечения данных. Как при использовании DataSet, так и при использовании DataReader провайдеры данных обеспечивают извлечение данных и сообщение с хранилищем данных. Объект Connection обеспечивает подключение к определенному хранилищу данных. Он может быть открыт либо при помощи метода Open, либо путем неявного открытия объекта при использовании DataAdapter. Объект Command работает в содружестве с объектом Connection для передачи параметров и применения команд к хранилищам данных. Результаты его выполнения помещаются в объект DataReader или DataSet. Примерами параметров могут служить операторы SQL, параметры хранимых процедур и возвращаемые значения. Объект DataReader предназначен для получения потока данных, доступных только для чтения. Этот объект используется совместно с объектами Command и Connection. Быстродействие этого объекта выше, чем у объекта DataSet. Но не забывайте, что пока объект DataReader используется, подключение к хранилищу данных остается активным. Для того чтобы разорвать подключение, вам потребуется закрыть данный объект. Объект DataAdapter используется для сообщения с базой данных при заполнении объекта DataSet. Он работает в содружестве с объектами Connection и Command для извлечения данных из хранилища. Кроме того, в DataAdapter реализованы функции записи в сами источники данных изменений, сохраняемых в объекте DataSet в локальной памяти. Пространства имен, используемые для доступа к данным Напомним, что пространства имен (namespace) представляют собой логические группы библиотек классов, облегчающие для разработчика поиск реализации программного кода, тематически связанных друг с другом. Вся основная функциональность ADO.NET размещается в пространстве имен System.Data. Таким образом, в любом модуле, в котором вы хотите использовать возможности доступа к данным, вам придется обязательно включать оператор Imports.System.Data. После объявления главного пространства имен вам понадобится также включить оператор Imports для управляемых провайдеров, с помощью которых вы будете извлекать данные. В ADO.NET имеется внутренняя поддержка для двух управляемых провайдеров: SqlClient и OleDB. Провайдер данных SQL Server (System.Data.SqlClient) необходимо использовать для обращения к базам данных SQL Server 7.0 и последующих версий. Он работает быстрее, чем провайдер OLE DB, поскольку обращается напрямую к SQL Server, минуя уровень OLE DB. Провайдер данных OLE DB (System.Data.OleDB) должен использоваться при обращении к любым провайдерам OLE DB, таким как Oracle, Microsoft Access, SQL Server (до версии 7.0) и другим. Кроме того, данный провайдер пригодится при необходимости совместного использования данных SQL Server и других баз данных (например, SQL Server и Oracle), поскольку он поддерживает одновременную работу с несколькими базами данных. Каждый из провайдеров содержит собственные объекты Connection, Command, DataReader и DataAdapter, так как реализует эти объекты собственным способом для соответствующего источника данных. Пространство имен System.Data.SqlClient содержит объекты: SqlConnection, SqlCommand, SqlDataReader, SqlDataAdapter. Пространство имен System.Data.OleDb содержит объекты: OleDbConnection, OleDbCommand, OleDbDataReader, OleDbDataAdapter. Механизмы извлечения данных из хранилищ с помощью управляемого провайдера Разберем использование пространства имен SqlClient и его классов для создания подключений к SQL Server с последующим извлечением и обработкой данных. Начнем наше обсуждение с объекта SqlConnection, принадлежащего к пространству имен SqlClient. Класс SqlConnection DataReader DataAdapter вместе с другими классами, содержащимися в Command пространстве имен System.Data.SqlClient, Connection был специально создан разработчиками Microsoft для использования с базами данных SQL Server. Поэтому он наилучшим образом оптимизирован для этой цели. Все свойства класса SqlConnection могут быть разделены на две большие группы: те свойства, которые передают параметры, и те, которые их принимают. К первой группе отнесем основное свойство класса: ConnectionString – строка инициализации подключения, которая включает в себя все атрибуты, необходимые для установки подключения к определенному SQL Server; ко второй группе относятся свойства, возвращающие: ConnectionTimeout – время ожидания соединения, DataBase – имя текущей базы данных, DataSource – имя экземпляра SQL Server, PacketSize – размер сетевого пакета, Провайдер данных ServerVersion – версию SQL Server, State – текущий статус подключения, WorkstationID – атрибут или имя локальной машины. Не все атрибуты являются обязательными, подробно их использование рассмотрено в практикуме к этой теме. Класс SqlConnection имеет три метода: для создания подключения – метод Open, для смены базы данных в текущем подключении – метод ChangeDatabase, для закрытия текущего подключения – метод Close. Для подключения к базе данных SQL Server при помощи пространства имен SqlClient вам необходимо написать программный код, который будет выглядеть приблизительно так: Imports System.Data.SqlClient Dim strConnection As String="server=Persist Security Info=False; Integrated Security=SSPI; database=HumanResources; server=abrzh" Dim cnn As New SqlConnection(strConnection) ‘Открытие подключения cnn.Open() ‘Извлечение данных и другие операции с использованием подключения cnn.ChangeDatabase(“Pubs”) ‘Закрытие подключения cnn.Close() Теперь, когда мы научились создавать объект подключения, перейдем к рассмотрению следующего объекта из пространства SqlClient – объекту SqlCommand. Объект SqlCommand предоставляет доступ к свойствам и методам, необходимым для выполнения любого запроса к источнику данных. Объект SqlCommand может применяться вместе с объектами DataReader или SqlDataAdapter. Объект SqlCommand имеет следующие свойства: DataReader DataAdapter CommandText – для описания SQLкоманд, имени Command хранимой процедуры или имени таблицы; Connection CommandTimeout – для определения длительности ожидания; CommandType – для определения типа команды; Connection – для описания имени объекта SqlConnection, который будет использоваться для выполнения соединения; Parameters – для описания коллекции параметров при выполнении хранимой процедуры; Transaction – для задания объекта SqlTransaction при обработке транзакций; UpdatedRowSource – свойство для совместного использования с методом Update объекта SqlDataAdapter. Провайдер данных Программирование свойств объекта SqlClient рассмотрим на примере свойства CommandText. Это свойство обязательно используется при работе с классом SqlClient. Этот пример демонстрирует выполнение команды, имеющей тип Text и выполняющей вызов оператора T-SQL в объекте SqlCommand (извлечение всех записей из таблицы nTable). Dim MySqlCmd As New SqlCommand() MySqlCmd.CommandType=CommandType.Text MySqlCmd.CommandText=”SELECT * FROM nTabel” Следующий пример показывает использование команды типа TableDirect, требующей от объекта SqlCommand извлечения всех строк и столбцов таблицы nTable. Dim MySqlCmd As New SqlCommand() MySqlCmd.CommandType=CommandType.TabelDirect MySqlCmd.CommandText=”nTable” И, наконец, при использовании команды типа StoredProcedure мы сообщаем объекту SqlCommand о необходимости выполнения хранимой процедуры sp_get_nTable. Dim MySqlCmd As New SqlCommand() MySqlCmd.CommandType=CommandType.StoredProcedure MySqlCmd.CommandText=”sp_get_nTable” Для класса SqlCommand существует ряд методов: Cancel – для отмены выполнения текущего оператора; CreateParameter – для создания объекта SqlParameter; ExecuteNonQuery – для выполнения команд. Которые не возвращают никаких данных; ExecuteReader – для выполнения операторов T-SQL, возвращающих данные в формате, отличном от XML; ExecuteScalar – для возвращения первого столбца первой строки множества данных, идеально подходит для выполнения таких операций, как Count(*), возвращающих единственную запись с одним полем; ExecuteXmlReader – для возвращения выходных данных в формате XML; Prepare – для подготовки и сохранения плана выполнения запроса с целью последующего выполнения команд SQL; ResetCommandTimeout – для установления свойства CommandTimeout. Объект DataReader обеспечивает быстрый вывод потоковых данных, предназначенных для чтения. Мы также обсуждали, что объект DataReader работает DataReader DataAdapter в режиме активного подключения, следовательно, Command необходимо наличие открытого Connection подключения во время извлечения записей из объекта DataReader для использования в вашем Провайдер данных приложении. Объект имеет следующие свойства: FieldCount – возвращает количество столбцов в текущей строке; Item – возвращает значение определенного столбца текущей строки; RecordsAffected – содержит количество записей, измененных SQL командами; Depth – определяет глубину вложенности текущей строки; IsClosed – определяет статус объекта DataReader в текущий момент. Объект имеет большое количество методов, из которых наиболее часто используется метод Read, позволяющий выполнять переход к следующей строке текущего результирующего множества. Объект DataAdapter обеспечивает связь DataReader DataAdapter между подключением к базе данных SQL Command Server и объектом DataSet, хранящим физические данные, Connection которые были получены при выполнении вашего запроса. Рассмотрим свойства объекта: AcceptChangesDuringFill – определяет, применялся ли метод AcceptChanges к объектам DataTable; ContinueUpdateOnError – используется при обработке исключений; DeleteCommand, InsertCommand, SelectCommand, UpdateCommand – используются при удалении, добавлении, заполнении, обновлении записей из DataSet; MissingMappingAction, MissingSchemaAction – используются при возникновении затруднений в сохранении пересылаемых данных; TableMappings – используется для определения схемы преобразования таблиц между DataSet и DataAdapter. Объект DataAdapter располагает методами: Fill – для вставки или обновления объекта Dataset с помощью данных, полученных из источника; FillSchema – вставляет в объект DataSet схему данных; GetFillParameters – принимает параметры, возвращенные свойством SelectCommand. Которые используются методом Fill; Update – вызывает соответствующие командные объекты INSERT, UPDATE и DELETE с целью внесения в источнике данных изменений, отражающих текущее состояние объекта DataSet. Провайдер данных Выводы С выходом Microsoft .NET Framework перед разработчиками программных приложений встает проблема не только знакомства с новыми возможностями программирования, но и освоение значительных изменений в технологиях доступа к данным через технологию ADO.NET. В настоящее время технология ADO.NET предоставляет в наше распоряжение целый ряд классов, предназначенных для извлечения и обработки данных. Применение классов ADO.NET становится важным условием при создании современных управляемых данными приложений. Вопросы для самопроверки 1. Чем ADO.NET отличается от ADO? 2. Что представляет собой объект DataReader, и как необходимо его использовать? 3. Что представляет собой объект DataAdapter, и как необходимо использовать его? 4. Что такое провайдер данных, и какую роль он играет? 5. В каком случае предпочтительно использовать провайдер SqlClient? 6. Как извлекать информацию из хранилищ данных при помощи пространства имен System.Data? Литература 1. Visual Basic.NET: учебный курс / В. Долженков, М. Мозговой. — СПб.: Питер, 2003. — 464 с.: ил. 2. Объектно-ориентированное программирование в Visual Basic.NET. Библиотека программиста / Д. Кларк. — СПб.: Питер, 2003. — 352 с.: ил. 3. Эпплман Д. Переход на VB.NET: стратегии, концепции, код. — СПб.: Питер, 2002. — 464 с.: ил. 4. Троелсен Э. C# и платформа .NET. Библиотека программиста — СПб.: Питер, 2006 — 796 с.: ил.