Объекты ADO. Изменение формы сущностных данных

03.04.2019

ГЛАВА 4

Модель ADO.NET: провайдеры данных

Порой кажется, что не успели еще разработчики приложений баз данных привыкнуть к новой технологии, как компания Microsoft предложила совершенно новую модель доступа к базам данных. В этой главе основное внимание уделяется модели ADO.NET, которая является наиболее новым воплощением модели ADO. Сначала обосновывается необходимость введения новой модели доступа к базам данных (с точки зрения авторов), а затем предлагается описание самой модели и ее архитектуры.

В этой главе преследуется цель изложить основные принципы функционирования технологии ADO.NET. Здесь обсуждаются базовые операции и описываются базовые объекты провайдера данных ADO.NET, в частности Connection, Command, Parameter и DataReader. Далее (в главах 5, "ADO.NET: объект DataSet", 6, "ADO.NET: объект DataAdapter", и 7, "ADO.NET: дополнительные компоненты") рассматриваются более сложные объекты, которые тесно связаны с основным объектом ADO.NET - DataSet.

Обзор технологии ADO.NET

Разработчики приложений для работы с базами данных на основе Visual Basic уже привыкли к тому, что Microsoft каждые несколько лет предлагает новую усовершенствованную модель доступа к данным. Кроме новой трехбуквенной аббревиатуры, технология ADO.NET также предлагает новую модель API-интерфейсов и объектов. В течение последних нескольких лет разработчики уже успели познакомиться с предшественниками ADO.NET - технологиями ODBC, DAO, RDO и ADO. При знакомстве с каждой новой технологией им требовалось тщательно изучить ее назначение и принципы работы. При этом они часто задавали себе один и тот же вопрос: имеет ли смысл переходить на новую технологию? В большинстве случаев ответ был положительным, если только новшества не оказывали никакого влияния на текущие и будущие требования проекта. Действительно, чаще всего переход на новые технологии был вполне обоснован, за исключением технологии RDO (Remote Data Objects) для проектов с процессором баз данных Jet (потому что технология ОАО по-прежнему является более удачной технологией работы с Jet).

Мотивация и философия

Итак, зачем же все-таки нужна новая объектная модель доступа к данным? Наиболее простой ответ на этот вопрос можно сформулировать по аналогии с рекламным лозунгом компании Toyota конца 1970-х годов: "Спрашивали? Так получите". Технология ADO.NET предоставляет множество функциональных возможностей, о которых разработчики мечтали с момента появления технологии ADO. Некоторые компоненты, например отсоединенные от источника данных наборы записей и поддержка XML, были добавлены в модель ADO уже после ее выпуска. Но, поскольку они являлись добавлениями к основной модели, которые отсутствовали в исходной архитектуре ADO, способ их применения был крайне неудобным.

Классическая модель ADO основана на модели COM и одном объекте recordset, применение которого может быть весьма разнообразным. В зависимости от параметров конфигурации, например типа курсора, его расположения и типа блокировки, объект recordset будет действовать по-разному и выполнять различные операции.

В технологии ADO.NET разные функции разделены и выполняются разными объектами, которые могут использоваться либо отдельно, либо вместе с другими объектами.

Это дает разработчику возможность специализированного применения объектов без дополнительного обременительного "багажа". В то же время совершенно разные объекты могут взаимодействовать друг с другом для выполнения более сложных функций.

Поддержка распределенных приложений и отсоединенной модели программирования

В технологии ADO.NET предусмотрена эффективная и гибкая поддержка приложений, распределенных между несколькими компьютерами (серверами баз данных, серверами приложений и клиентскими рабочими станциями). В частности, особая поддержка предусмотрена для отсоединенных (трехуровневых или n-уровневых) приложений с минимизацией нагрузки при работе с параллельными операциями доступа к данным и блокировкой ресурсов сервера базы данных. В результате повышаются возможности масштабирования приложений, т.е. поддержки большего количества параллельно работающих пользователей за счет постепенного увеличения количества клиентских компьютеров. Это преимущество имеет особенно большое значение при создании Web-приложений.

Расширенная поддержка XML

Хотя классическая модель ADO способна сохранять и считывать данные в формате XML, фактически используемый для этого формат имеет несколько необычную форму и не так прост в применении. Кроме того, поддержка XML в модели ADO была добавлена в ходе ее эволюции, а потому обладает некоторыми ограничениями, в то время как поддержка XML в технологии ADO.NET является ее ключевым элементом. Философия ADO.NET формулируется очень кратко и просто: "Данные - это данные". Независимо от источника поступления, они могут считываться и обрабатываться как реляционные или иерархические данные, исходя из поставленной задачи и используемых инструментов.

XML используется как формат передачи данных между уровнями и компьютерами. Это не только исключает проблему прохождения COM-объектов через брандмауэры, но и позволяет совместно использовать данные сразу несколькими приложениями, которые работают на платформах, отличных от Windows (так как практически любая платформа способна обрабатывать текстовые данные XML).

Интеграция с.NET Framework

ADO.NET – это не просто следующая версия ADO, она специально предназначена для использования на платформе.NET Framework. Код всех объектов ADO.NET полностью управляемый, т.е. работает под управлением платформы.NET Framework. Технология ADO.NET является составной частью платформы.NET Framework, что позволяет избежать проблем с контролем версий объектов, которые хорошо известны разработчикам, имеющим опыт работы с ADO.

Внешний вид объектов ADO.NET

Хотя ADO.NET является составной частью платформы.NET Framework, многие ее компоненты будут знакомы опытным разработчикам, поскольку внешне они во многом напоминают объекты ADO. Даже совершенно новые элементы ADO.NET реализованы так, чтобы максимально упростить процесс их изучения и применения на основе имеющихся знаний.

ADO.NET И ADO 2.X

При работе с моделью ADO.NET нужно учитывать перечисленные ниже отличия от классической модели ADO.

В классической модели ADO предусмотрен присоединенный к источнику данных способ доступа и использование физической модели данных.

В модели ADO.NET проводиться четкое разделение между присоединенным способом доступа к данным и отсоединенной моделью программирования.

В модели ADO.NET нет свойств CursorType, CursorLocation или LockType, потому что в ADO.NET предусмотрены только статические курсоры, клиентские курсоры и оптимистическая блокировка.

Вместо использования простого многоцелевого объекта recordset в ADO.NET разные функции распределены среди объектов меньшего размера - DataReader, DataSet и DataTable.

В ADO.NET разрешается полноценное манипулирование данными в формате XML, а не только использование его в качестве формата ввода-вывода данных.

В ADO.NET предусмотрена поддержка строго типизированных наборов данных DataSet, а не использование для всех полей типа Variant. Это позволяет эффективнее обнаруживать ошибки времени выполнения и повышает производительность работы приложений.

Место ADO.NET в архитектуре.NET Framework

На рис. 4.1 показано место классов ADO.NET в архитектуре.NET Framework. В основе этой платформы лежит общеязыковая исполняющая среда (Common Language Runtime - CLR), которая образует единую среду выполнения для всех.NET-совместимых приложений, независимо от используемого языка программирования. Среда CLR включает общую систему типов, управление памятью и жизненным циклом объектов.

На следующем логическом уровне над средой CLR располагаются базовые системные классы. Именно эти классы отвечают за выполнение базовых функций, которые могут использоваться в.NET-приложениях. На рис. 4.1 показаны только некоторые классы библиотеки классов.NET Framework, которая, по сути, является новым набором API-интерфейсов Windows. В прошлом доступ к функциям операционной системы Windows осуществлялся только через API-интерфейсы, которые состояли из большого набора разрозненных и плохо продуманных функций. На платформе.NET Framework такой доступ организован на основе свойств и методов, которые предлагаются базовыми системными классами. Это объектно-ориентированный, последовательный и комфортабельный способ создания приложений Windows, независимо от типа клиентского приложения: традиционного настольного приложения, броузера или Web-службы.

РИС. 4.1. Классы ADO.NET в структуре платформы.NET Framework


Этот уровень включает несколько пространств имен (групп классов и других определений), предназначенных для организации доступа к данным: System.Data, System.OleDb и System.Data.SqlClient. В оставшейся части данной главы, а также в главах 5, 6 и 7 эти классы и пространства имен рассматриваются более подробно.

Прикладные интерфейсы

На этом наиболее высоком уровне происходит дифференциация, или разделение, выполняемых функций, которые разработчики могут использовать в разных типах приложений. Он содержит классы и элементы управления для создания (классических) приложений Windows на основе форм (Windows Forms), другие классы и элементы управления для создания Web-ориентированных приложений (Web Forms), а также классы для создания приложений на основе Web-служб. Однако все они используют для прикладной логики базовую библиотеку классов - системные базовые классы.

Теперь после первого знакомства с расположением классов ADO.NET в общей структуре платформы.NET Framework рассмотрим подробнее основные объекты ADO.NET.

Провайдеры данных ADO.NET

Несмотря на подчеркнутое значение отсоединенной модели программирования, для извлечения, обновления, вставки и удаления данных все же придется подключиться к физической базе данных. Программное обеспечение ADO.NET для подсоединения и взаимодействия с физической базой данных называется провайдером данных ADO.NET. Провайдер данных (data provider) - это управляемый код.NET, который эквивалентен провайдеру OLEDB или драйверу ODBC. Провайдер данных состоит из нескольких объектов, которые реализуют необходимую функциональность в соответствии с определениями своих классов и интерфейсов.

В настоящее время существует три разных провайдера данных ADO.NET, каждый из которых определен в своем собственном пространстве имен. Для всех объектов в этих пространствах имен используются следующие префиксы: OleDb, Sql и Odbc. Однако при упоминании этих объектов в рамках своего пространства имен имя объекта можно указывать без употребления префикса данного пространства имен.

Провайдер данных SqICIient

Оптимизирован для работы с SQL Server версии 7.0 (или выше) и позволяет добиться более высокой производительности по следующим причинам:

Взаимодействует с базой данных непосредственно через собственный протокол табличной передачи данных (Tabular Data Stream - TDS), а не через OLEDB с отображением интерфейса OLEDB на протокол TDS;

Исключает накладные расходы, связанные с использованием COM-служб взаимодействия;

Отсутствуют ненужные функции, которые не поддерживаются в SQL Server (объекты этого провайдера данных находятся в пространстве имен System.Data.SqlClient).

Провайдер данных Oledb

Основан на существующем COM-поставщике OLEDB и COM-службах взаимодействия платформы.NET Framework, предназначенных для доступа к базе данных. Этот провайдер данных используется для работы с SQL Server более ранних версий, чем 7.0. Он позволяет осуществлять доступ к любой базе данных, для которой имеется поставщик OLEDB. Объекты этого провайдера данных находятся в пространстве имен System.Data.Oledb.

Провайдер данных Odbc

Используется для доступа к базам данных, которые не имеют собственного провайдера данных.NET или COM-поставщика OLEDB. Иногда драйвер ODBC демонстрирует более высокую производительность, чем драйвер OLEDB, поэтому для сравнения их фактической производительности при работе с конкретной базой данных рекомендуется провести ряд тестов. Объекты этого провайдера данных находятся в пространстве имен System. Data.Odbc.

НА ЗАМЕТКУ

Создание провайдера данных для ODBC несколько задержалось и отстало от создания платформы.NET Framework и Visual Studio .NET. Поэтому он не был включен в исходный выпуск Visual Studio .NET и его можно скопировать с Web-узла компании Microsoft. Кроме того, в скором будущем следует учитывать возможное появление дополнительных.NET-совместимых провайдеров данных.

В настоящее время на Web-узле компании Microsoft также можно скопировать провайдер данных Oracle.NEТ. Эти провайдеры данных ОDBС и Oracle будут включены в следующую версию 1.1 платформы.NET Framework и Visual Studio .NET 2003. В результате этого пространство имен провайдера данных ODBC Microsoft.Data.Odbc станет называться System.Data.Odbc.

В примерах этой главы используется провайдер данных ODBC версии 1.0, поэтому при использовании провайдера данных ODBC версии 1.1 нужно изменить имя его пространства имен.

Основные объекты

Каждый провайдер данных имеет четыре основных объекта, которые указаны в табл. 4.1.

Таблица 4.1. Основные объекты провайдера данных

Каждый объект основан на базовом родовом классе и реализует родовой интерфейс, но имеет собственную реализацию. Например, объекты SqlDataAdapter, OleDBDataAdapter и OdbcDataAdapter являются производными от класса DbDataAdapter и реализуют те же интерфейсы. Однако каждый из них реализует их своим собственным способом для соответствующего источника данных.

Пространство имен System. Data. OleDb содержит объекты:

OleDbConnection;

OleDbDataReader;

OleDbDataAdapter.

Пространство имен System.Data.SqlClient содержит объекты:

SqlConnection;

SqlDataReader;

SqlDataAdapter.

Пространство имен Microsoft.Data.Odbc содержит объекты:

OdbcConnection;

OdbcDataReader;

OdbcDataAdapter.

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

Объект Connection

Этот объект модели ADO.NET очень похож на объект Connection в классической модели ADO. Его предназначение очевидно: он служит для установления соединения с заданным источником данных и с указанным в строке подключения учетным именем и паролем. Соединение можно настроить, редактируя нужным образом значения параметров строки подключения. Объект Command (или DataAdapter) может затем использовать это подключение для выполнения нужных операций с источником данных.

НА ЗАМЕТКУ

В отличие от объекта Connection в модели ADO в объекте Connection в модели ADO.NET нет методов Execute и ОpenSchema. Для выполнения команд SQL следует использовать объекты Command или DataAdapter. Функции метода OpenSchema реализуются с помощью методов GetOleSchemaTable объекта OleDbConnection.

Хотя объекты OleDbConnection, SqlConnection и OdbcConnection реализуют одинаковые интерфейсы, они все же имеют разные реализации. Например, они имеют разный формат строки подключения. В объекте OleDbConnection используется стандартный формат строки подключения OLEDB с незначительными исключениями. В объекте OdbcConnection также используется стандартный формат строки подключения ODBC, но с незначительными отклонениями. Наконец, в объекте SqlConnection используется совершенно другой формат строки подключения, который имеет отношение только к SQL Server версии 7.0 или выше.

Более того, некоторые объекты обладают дополнительными свойствами. Например, объект OleDbConnection имеет свойство Provider для указания используемого провайдера данных OLEDB, а объект OdbcConnection имеет свойство Driver для указания используемого драйвера ODBC. Объект SqlConnection вообще не имеет этих свойств, так как используется с предопределенным источником данных, т.е. с SQL Server. Однако он имеет свойства PacketSize и WorkstationID, которые используются только для работы с SQL Server и не нужны для других типов подключения.

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

1. Запустите интегрированную среду разработки приложений Visual Studio .NET.

2. Создайте новый проект Visual Basic Windows Application. Для этого в диалоговом окне New Project (Новый проект) выберите тип проекта Visual Basic Project в области Project Types (Типы проектов), а затем шаблон Windows Application (Приложение Windows) в области Templates (Шаблоны).

3. Назовите проект DataProviderObjects.

6. В окне Properties укажите значение Data Provider Objects для свойства Text формы Form1.

7. В верхнем левом углу формы создайте кнопку, перетаскивая ее из панели элементов управления.

8. В окне Properties укажите значение cmdConnection для свойства (Name) и значение Connection для свойства Text этой кнопки.

9. В верхнем правом углу формы создайте текстовое поле, перетаскивая его из панели элементов управления.

10. В окне Properties укажите значение txtResults для свойства (Name), значение True для свойства Multiline и значение Both для свойства ScrollBars этого текстового поля.

11. Увеличьте размер текстового поля, чтобы оно занимало до 80% всей площади формы.

По окончании этих операций форма будет выглядеть так, как на рис. 4.2.


РИС. 4.2. Форма Form1 проекта DataProviderObjects


Перейдите в окно редактирования кода формы и включите в верхнюю часть файла приведенные ниже строки, которые импортируют пространства имен, используемые здесь и в следующих примерах главы.

Обратите внимание, что эти пространства имен содержат классы и определения объектов ADO.NET для каждого провайдера данных.

НА ЗАМЕТКУ

Среда Visual Studio .NET может не обнаружить пространство имен Data.Odbc, потому что оно является расширением базовой версии продукта. В таком случае выполните ряд действий.

1. Скопируйте инсталлятор провайдера данных ODBC с Web-узла компании Microsoft и выполните все инструкции по инсталляции.

2. В окне SolutionExplorer щелкните правой кнопкой мыши на папке References проекта DataProviderObjects.

3. Выберите в контекстном меню команду Add Reference.

4. Во вкладке.NET диалогового окна Add Reference прокрутите список компонентов и найдите файл Microsoft.Data.Odbc.dll.

5. Щелкните дважды на файле Microsoft.Data.Odbc.dll для включения его в список избранных компонентов Selected Components в нижней части диалогового окна Add Reference.

6. Щёлкните на кнопке ОК для закрытия диалогового окна Add Reference.

Если по какой-либо причине не распознано какое-то другое импортированное пространство имен, потребуется привести ссылку на файл System.Data.dll. Для этого выполните действия, перечисленные в пп. 2-6, где вместо файла Microsoft.Data.Odbc.dll при выполнении п. 4 нужно использовать файл System.Data.dll.

Теперь для кнопки btnConnection нужно создать код, приведенный в листинге 4.1, для создания подключения к базе данных pubs сервера SQL Server. Этот код создает подключение и отображает состояние подключения до и после попытки подключения к базе данных.

Листинг 4.1. Код открытия подключения и отображения его состояния
Private Sub btnConnection Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnConnection.Click
" Открытие подключения
txtResults.Text & "Opening DB connection…" _
& ControlChars.CrLf & ControlChars.CrLf
" Отображение состояния подключения
If (cnn.State = System.Data.ConnectionState.Open) Then
txtResults.Text = txtResults.Text & "Connection is Open"
txtResults.Text = txtResults.Text & "Connection is Closed"
txtResults.Text = txtResults.Text & ControlChars.CrLf
СОВЕТ

Новым полезным компонентом Visual Basic .NET является возможность получения текстового представления для значений перечисления (enum) вместо создания специальной подпрограммы на основе операторов select-case для всех возможных значений перечисления. Все типы перечисления, которые являются объектами, наследуют метод ToString, возвращающий строку с текстовым представлением текущего значения. В листинге 4.1 используется приведенный ниже фрагмент кода для отображения состояния подключения на основе операторов if-else.

" Отображение состояния подключения – вариант 1
If (cnn.State = System.Data.ConnectionState.Open) Then
txtResults.Text = txtResults.Text& "Connection is Open"
txtResults.Text = txtResults.Text& "Connection is Closed

Его можно заменить другим вариантом кода, содержащим только одну строку.

" Отображение состояния подключения вариант 2
txtResults.Text & "Connection is " & cnn.State.ToString & ControlChars.CrLf

После запуска полученного приложения DataProviderObjects и щелчка на кнопке Connection в текстовом поле появятся строки о закрытии подключения, о состоянии подключения и повторном открытии подключения, как показано на рис. 4.3.

НА ЗАМЕТКУ

При создании рабочего кода нужно выбрать и реализовать стратегию обработки исключительных ситуаций для большинства подпрограмм и операций. Обычно основана на блоках try-catch обработки исключительных ситуаций. Этот код не включен в приведенные здесь примеры, потому что наша цель - сфокусировать внимание на концепциях программирования баз данных, а не на описании общих принципов программирования для Visual Basic .NET.

Объект Command

Аналогично объекту Connection, объект Command модели ADO.NET очень похож на своего предшественника из прежней модели ADO 2.X. Объект Command позволяет выполнять команды по отношению к источнику данных и получать возвращенные данные или результаты выполнения команд.


РИС. 4.3. Состояние приложения DataProviderObjects до и после открытия подключения с помощью кода из листинга 4.1


Этот объект имеет следующие свойства: CommandText и СommandType для определения текста и типа фактической команды; Connection для указания подключения, используемого для выполнения команды; СommandTimeout для указания времени ожидания, по истечении которого команда отменяется и выдается сообщение об ошибке; Parameters для коллекции параметров команды; Transaction для указания транзакции, в которой используется данная команда.

Все три версии объекта Command (в пространствах имен OleDb, Sql, Odbc) имеют идентичные свойства и методы, за исключением того, что объект SqlCommand имеет дополнительный метод, которого нет у двух других вариантов этого объекта, а именно ExecuteXmlReader. Он использует преимущества SQL Server для автоматического возвращения данных в формате XML (если в запрос SQL добавлено предложение FOR XML).

НА ЗАМЕТКУ

Еще одно отличие между версиями объекта Command для разных провайдеров данных заключается в использовании значений свойства CommandType. Все они поддерживают значения Text и StoredProcedure, а объекты OleDbCommand и SqlCommand поддерживают еще одно, третье возможное значение - TableDirect. Это позволяет эффективно загружать все содержимое таблицы за счет установки значения TableDirect для свойства CommandType и имени таблицы для свойства CommandText.

Продолжим работу с формой, показанной на рис. 4.3.

1. Добавим еще одну кнопку сразу под кнопкой btnConnection, перетаскивая пиктограмму кнопки из панели элементов управления.

2. В окне свойств Properties установите значение btnCommand для свойства Name и значение Command для свойства Text.

3. Добавьте для кнопки код, показанный в листинге 4.2.

Листинг 4.2. Код открытия подключения к базе данных и подготовки объекта Command
" Создание экземпляра объекта Connection
" Создание экземпляра объекта Command
Dim cmd As SqlCommand = New SqlCommand() txtResults.Clear()
"Select au_lname, state from authors"
" Вывод текста команды
txtResults.Text = txtResults.Text & ControlChars.Tab & cmd.CommandText() & ControlChars.CrLf

После запуска на выполнение приложения DataProviderObjects щелкните на кнопке Command, и в текстовом поле будет показана команда SQL, которая находится в свойстве CommandText объекта SqlCommand, а именно: SELECT au_lname, state FROM authors.

НА ЗАМЕТКУ

Многие классы платформы.NET Framework, а также созданные другими разработчиками классы перегружают конструкторы объектов. Иначе говоря, существует несколько способов создания нового экземпляра класса, где каждый конструктор принимает свойственный только ему набор аргументов. Таким образом можно выбрать версию, оптимальную для выполнения текущей задачи. Конструктор в листинге 4.2 для объекта SqlConnection отличается от го по умолчанию конструктора в листинге 4.1, в котором не используется никаких аргументов. Позже строке подключения присваивается объект SqlConnection с помощью свойства ConnectionString.

" Создание экземпляра объекта Connection
Dim cnn As SqlConnection = New SqlConnection()
" Создание строки подключения
cnn.ConnectionString = "server=localhost;uid=sa;database=pubs"

В листинге 4.2 используется конструктор объекта SqlConnection, который принимает строку подключения в качестве параметра. Это позволяет создать объект и сразу же указать для него строку подключения в одной строке кода.

" Создание экземпляра объекта Connection
Dim cnn SqlConnection = New SqlConnection("server=localhost;uid-sa;database=pubs")

Применение объекта Command с параметрами и хранимыми процедурами

При создании запросов или команд для источника данных часто требуется передавать значения параметров действия (обновление, вставка или удаление данных) или хранимой процедуры. Для решения этой проблемы в объекте Command предусмотрено свойство Parameters, которое является объектом-коллекцией ParameterCollection и содержит коллекцию объектов-параметров Parameter. Это аналогично способу работы, применимому в модели ADO 2.X.

Объекты Parameter и ParameterCollection тесно связаны с соответствующим провайдером данных, поэтому они должны быть реализованы как составная часть провайдера данных ADO.NET. Способы программирования объекта SqlParameterCollection и использование объектов OdbcParameterCollection и OledbParameterCollection имеют существенные отличия. Объекты OdbcParameterCollection и OledbParameterCollection основаны на позиционных параметрах, а объект SqlParameterCollection – на именованных параметрах. Эти различия в значительной степени влияют на способ определения запросов и параметров.

Начнем с создания простого запроса с параметрами для извлечения из базы данных pubs имен и фамилий всех авторов из заданного штата.

С одной стороны, при использовании провайдеров данных OLEDB или ODBC запрос будет иметь следующий вид:

SELECT state, au_fname, au_lname from authors WHERE state = ?

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

С другой стороны, при использовании провайдера данных SqlClient запрос будет выглядеть следующим образом:

SELECT state, au_fname, au_lname from authors WHERE state = @MyParam

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

Объект Parameter можно создать явно, используя конструктор Parameter (т.е. с использованием оператора New) или передавая нужные аргументы методу Add объекта-коллекции ParameterCollection (свойство Parameters объекта Command). Помните, что оба метода (конструктор Parameter и метод Add) имеют перегруженные версии.

Ниже приведен один из способов включения параметра команды за счет явного указания объекта-параметра.

Dim rayParameter As New OdbcParameter("@MyParam", OdbcType.Char, 2)

А способ включения параметра команды с помощью метода Add выглядит иначе.

Второй метод короче и обычно предпочтительнее, если только нет особой причины для повторного использования объекта Parameter.

Для метода Add объекта Parameter обычно требуется указать имя, тип и длину параметра. Затем нужно указать направление передачи данных: Input, Output, InputOutput или ReturnValue. По умолчанию используется направление Input. Наконец, для присвоения значения параметру нужно использовать свойство Value объекта Parameter. Кроме того, для параметра можно указать другие свойства, например масштаб (свойство Scale), точность (свойство Precision) и допустимость использования неопределенных значений (свойство IsNullable).

При использовании провайдера данных SqlClient можно применять практически идентичный код. Единственным отличием являются префиксы Odbc вместо префиксов Sql, а также тип перечисления SqlDbType вместо OdbcType.

Dim myParameter As New SqlParameter("@MyParam", SqlDbType.Char, 2)
myParameter.Direction = ParameterDirection.Input
cmd.Parameters.Add(myParameter)

Аналогично выглядит способ включения параметра команды с помощью метода Add.

cmd.Parameters("@MyParam").Direction = ParameterDirection.Input
cmd.Parameters("@MyParam").Value = "CA"
СОВЕТ

Для передачи параметру неопределенного значения можно использовать свойство Value объекта DBNull.

cmd.Parameters("@MyParam").Value = DBNull.Value

Измените код кнопки cmdButton, как показано в листинге 4.3. После запуска программы и щелчка на кнопке cmdButton в текстовом поле появится текст запроса, а также имя и значение параметра.

Листинг 4.3. Код подготовки и отображения команды и ее параметров
Private Sub btnCommand_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnCommand.Click
" Создание экземпляра объекта Connection
Dim cnn As SqlConnection = New SqlConnection(_
"server=localhost;uid=sa;database=pubs")
" Создание экземпляра объекта Command и объектов Parameter
Dim prm As SqlParameter = New SqlParameter()
" Открытие подключения cnn.Open()
" Указание подключения и текста команды
cmd.CommandType = CommandType.Text
"Select au_lname, state from authors where state = @MyParam"
cmd.Parameters.Add(New SqlParameter("@MyParam", SqlDbType.Char, 2))
cmd.Parameters("@MyParam").Value = "CA"
" Вывод текста команды
txtResults.Text = "Command String:" & ControlChars.CrLf
cmd.CommandText() & ControlChars.CrLf
" Вывод параметров команды
txtResults.Text = txtResults.Text & "Command parameters:" & _
For Each prm In cmd. Parameters
txtResults.Text = txtResults.Text & ControlChars.Tab & _
prm.ParameterName & " = " & prm.Value & ControlChars.CrLf

Аналогично вызываются хранимые процедуры, за исключением того, что вместо свойства CommandType.Text используется свойство CommandType.StoredProcedure, а имя хранимой процедуры присваивается свойству CommandText. Таким образом, код вызова хранимой процедуры GetAuthorsFromState с двухсимвольным параметром для извлечения информации обо всех авторах заданного штата будет выглядеть, как показано ниже.

cmd.CommandText = "GetAuthorsFromState"
cmd.Parameters.Add("@MyParam", SqlDbType.Char, 2)
cmd.Parameters("@MyParam").Direction = ParameterDirection.Input
cmd.Parameters("@MyParam").Value = "CA"
СОВЕТ

Для вызова хранимой процедуры с помощью OdbcCommand нужно использовать стандартные последовательности символов ODBC (с участием фигурных скобок), а не только имя процедуры для свойства CommandText. В качестве заменителей параметров в ODBC используются вопросительные знаки. Вот как выглядит приведенный выше для провайдера данных ODBC:

cmd.CommandType = CommandType.StoredProcedure
cmd.CommandText = "{GetAuthorsFromState ?}"
cmd.Parameters.Add("@MyParam", OdbcType.Char, 2)
cmd.Parameters("@MyParam").Direction = ParameterDirection.Input
cmd.Parameters("@MyParam").Value = "CA"

Хранимая процедура также возвращает значение, которое указывается с помощью специальной последовательности символов (вопросительного знака и знака равенства) у открывающей скобки, как показано ниже.

cmd.CommandText = "{? = GetAuthorsFromState ?}"

Чтобы хранимая процедура возвращала значение, нужно указать направление Output, а затем считать значение свойства параметра после вызова хранимой процедуры. В данном примере также определяется возвращаемое значение хранимой процедуры. Поскольку здесь указан тип Int сервера SQL Server, то для этого параметра не нужно указывать длину, так как по определению она составляет 4 байт.

cmd.Parameters.Add(New SqlParameter("result", SqlDbType.Int)
cmd. Parameters ("result").Direction = ParameterDirection.ReturnValue
cmd.Parameters.Add(New SqlParameter("@MyParam", SqlDbType.Int)
cmd.Parameters("@MyParam").Direction = ParameterDirection.Output
" Вызов хранимой процедуры
Msg (cmd.Parameters("@MyParam").Value)
НА ЗАМЕТКУ

При определении параметра, который будет использоваться для возвращаемого значения ReturnValue хранимой процедуры его нужно указать первым в списке параметров коллекции Parameters. Это обязательное условие для провайдеров данных OLEDB и ODBC, потому что, как отмечалось выше, параметры этих провайдеров определяются по порядку их расположения, а возвращаемое значение может располагаться только с начала. Однако при определении возвращаемого значения для провайдера данных SQL его можно pасполагать в произвольном месте коллекции параметров, потому что параметры провайдера данных SQL определяются по именам.

Выполнение команд

До сих пор мы только указывали свойства и параметры объекта Command, но не выполняли эти команды. Существует три стандартных способа выполнения команд для объекта Command и один способ для объекта SqlCommand.

Метод ExecuteNonQuery. Выполняет команду SQL и не возвращает записей.

Метод ExecuteScalar. Выполняет команду SQL и возвращает первое поле первой записи.

Метод ExecuteReader. Выполняет команду SQL и возвращает набор записей с помощью объекта DataReader.

Метод ExecuteXmlReader (только для объекта-команды SqlCommand). Выполняет команду SQL и возвращает набор записей в формате XML с помощью объекта XmlReader.

Метод ExecuteNonQuery

Этот метод позволяет выполнять команды без возвращения значений (наборов записей или скалярных значений), кроме значения, сообщающего об успешном или неудачном исходе выполнения команды. Это наиболее эффективный способ выполнения команд по отношению к источнику данных. Таким образом можно выполнять команды SQL или хранимые процедуры, которые являются DDL-командами определения данных (например, для создания или изменения структуры базы данных: таблиц, представлений или хранимых процедур) либо DML-командами управления данными (например, их обновления, вставки или удаления).

НА ЗАМЕТКУ

Метод ExecuteNonQuery возвращает только целочисленное значение, сообщающее об успешном или неудачном исходе выполнения команды.

При удачном выполнении DDL-команд определения данных для изменения структуры баз данных возвращается значение -1, а при удачном выполнении DML управления данными для их обновления, вставки или удаления возвращается количество строк, задействованных в команде. При неудачном выполнении команд обоих типов возвращается значение 0.

Продолжая работу с проектом DataProviderObjects, попробуем использовать объекты пространства имен OleDb и базу данных pubs. Наша задача – создать новую таблицу tblStateZipCodes для этой базы данных с помощью DDL-команды. Новая таблица tblStateZipCodes предназначена для организации связи между почтовыми индексами и штатами. Определения ее полей совпадают с определениями полей в других таблицах базы данных pubs, но отличаются от определений полей в других таблицах базы данных Novelty. Эта таблица имеет два поля: ZipCode для почтового индекса и State для названия соответствующего штата. Ниже приведена команда SQL для создания этой таблицы.

CREATE TABLE tblStateZipCodes (

Теперь нужно изменить исходную форму Form1, выполнив ряд действий.

1. Откройте форму Form1 в интегрированной среде разработки Visual Studio .NET.

2. В верхнем левом углу формы создайте еще одну кнопку, перетаскивая ее пиктограмму из панели элементов управления.

3. В окне свойств Properties укажите значение btnNonQuery для свойства (Name) и значение ExecuteNonQuery для свойства Text.

Затем создайте код подпрограммы btnNonQuery_Click, который приведен в листинге 4.4.

Листинг 4.4. Код создания таблицы базы данных с помощью объектов пространства имен OleDb
Private Sub btnNonQuery_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnNonQuery.Click
Dim sql As String Dim result As Integer
Dim cmd As OleDbCommand = New OleDbCommand()
" Указание подключения и текста команды
cmd.CommandType = CommandType.Text
" Указание команды SQL для создания новой таблицы
sql = "CREATE TABLE tblStateZipCodes (" & _
"ZipCode char (5) NOT NULL, " & _
MsgBox(sql) cmd.CommandText = sql
" Открытие подключения перед вызовом метода ExecuteNonQuery.
" Для обработки исключительных ситуаций нужно поместить
" код в блоке Try-Catch, потому что неудачное выполнение
" команды ТАКЖЕ генерирует ошибку времени выполнения.
" Отображение сообщения об ошибке.
" Вывод результатов выполнения команды.
MessageBox.Show("Command completed successfully")
" MessageBox.Show("Команда выполнена успешно")
MessageBox.Show("Command execution failed")
" MessageBox.Show("Команда не выполнена")

После запуска полученного приложения и щелчка на кнопке ExecuteNonQuery сначала появится диалоговое окно с сообщением об успешном выполнении команды. Правильность выполнения команды можно проверить, просматривая список таблиц базы данных pubs в диалоговом окне Server Explorer интегрированной среды разработки Visual Studio .NET (которое описывается в главе 1, "Основы построения баз данных") или в программе SQL Server Enterprise Manager (которая рассматривается в главе 3, "Знакомство с SQL Server 2000").

При повторном щелчке на кнопке ExecuteNonQuery появятся два диалоговых окна с сообщениями: одно с сообщением о возникшей исключительной ситуации (оно создается блоком обработки исключительных ситуаций try-catch), а другое - о неудачном выполнении команды.

Аналогичным способом можно создать представление или хранимую процедуру. Для создания представления EmployeeJobs_view, которое возвращает отсортированный по должностям перечень сотрудников с указанием их имен, фамилий и должностей, замените команду SQL в листинге 4.4 приведенной ниже командой.

sql = "CREATE VIEW EmployeeJobs_view AS" & _
"SELECT TOP 100 PERCENT jobs. job_desc," & _
"employee.fname, employee.lname" &_
"employee ON jobs. job_id = employee. job_id &_
НА ЗАМЕТКУ

Для включения предложения ORDER BY в определение представления с сортировкой результатов нужно включить в команду SELECT предложение ТОР.

Для создания хранимой процедуры, которая принимает один параметр и возвращает значение, нужно изменить эту команду SQL, как показано в листинге 4.5.

Листинг 4.5. Код, содержащий команду SQL для создания хранимой процедуры AuthorsInState1
sql = "CREATE PROCEDURE AuthorsInState1 @State char(2)" & _
" AS declare @result int" & _
" select @result = count (*) from authors " & _
НА ЗАМЕТКУ

Хотя метод не возвращает записи, входные и выходные параметры, а также возвращаемые значения можно передавать или возвращать с помощью коллекции Parameters. Это более эффективный подход, чем выполнение команды, которая возвращает набор записей или скалярное значение.

Обратимся теперь ко второму типу команд SQL для управления данными, т.е. их обновления, вставки или удаления. Для этих команд обычно требуется указать параметры, особенно при работе с хранимыми процедурами.

Продолжая работу с проектом DataProviderObjects, предположим, что издательство, которое создало базу данных pubs, решило повысить авторам выраженный в процентах гонорар. Включение новой кнопки и нового текстового поля в форму позволяет главному бухгалтеру издательства повысить гонорары авторов с помощью параметра команды UPDATE. Для этого нужно выполнить перечисленные ниже действия.

1. Создайте новую кнопку под кнопкой cmdExecuteNonQuery.

2. В окне свойств Properties для этой кнопки укажите значение cmdUpdate для свойства (Name) и значение Update для свойства Text.

3. Создайте новое текстовое поле под новой кнопкой Update.

4. В окне свойств Properties для этого текстового поля укажите значение txtParam1 для свойства (Name) и значение 0 для свойства Text. Установка такого значения гарантирует, что при запуске программы и случайном нажатии кнопки Update не будет причинен ущерб данным.

5. Создайте код подпрограммы btnUpdate_Click, приведенный в листинге 4.6.

Листинг 4.6. Код обновления таблицы базы данных с помощью команды UPDATE с параметром
Private Sub btnUpdate_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnUpdate.Click
" Создание экземпляра объекта Connection.
Dim cnn As SqlConnection = New SqlConnection(_
"server=localhost;uid=sa;database=pubs")
" Создание экземпляра объекта Command.
Dim cmd As SqlCommand = New SqlCommand()
cmd.CommandType = CommandType.Text
cmd.CommandText = "UPDATE roysched SET royalty = royalty + @param1"
" Создание параметра и указание его значения.
cmd.Parameters.Add(New SqlParameter("@param1", SqlDbType.Int))
cmd.Parameters("@param1").Direction = ParameterDirection.Input
cmd.Parameters("@param1").Value = Val(txtParam1.Text)
" Открытие подключения перед вызовом метода ExecuteReader().
result = cmd.ExecuteNonQuery()
MessageBox.Show(result & " records updated", "DataProviderObjects")

Теперь таблицу с гонорарами авторов в базе данных pubs можно обновить, запустив приложение DataProviderObjects, задав новое значение гонорара в текстовом поле под кнопкой Update и щелкнув на этой кнопке. После этого на экране появится диалоговое окно с указанием количества охваченных записей. Этот результат можно проверить с помощью программы SQL Server Enterprise Manager, просматривая данные о гонорарах в таблице roysched до и после обновления.

Точно такое же обновление можно выполнить с помощью хранимой процедуры, что позволяет добиться более высокой производительности и централизованно хранить код. Потенциальным недостатком использования хранимых процедур является необходимость назначения администратора базы данных или специалиста с опытом создания хранимых процедур. В крупных организациях порой уходят целые дни на то, чтобы администратор базы данных изменил хранимые процедуры, которые можно самостоятельно изменить за несколько минут. Хранимые процедуры создаются с помощью программ SQL Server Enterprise Manager или SQL Query Analyzer, которые описаны в главе 3, "Знакомство с SQL Server 2000". Это можно также сделать с помощью проекта DataProviderObjects, изменив команду SQL, как это делалось ранее.

Итак, в данном примере хранимая процедура имеет следующий вид:

CREATE PROCEDURE UpdateRoyalties
UPDATE roysched SET royalty = royalty + @param1

В листинге 4.6 для организации вызова хранимой процедуры потребуется заменить свойства CommandText и CommandType объекта Command.

cmd.CommandType = CommandType.StoredProcedure
cmd.CommandText = "UpdateRoyalties"

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

Метод ExecuteScalar

Иногда нужно выполнить команду, которая возвращает скалярное значение, т.е. только одно значение. Типичными примерами являются команды SQL для вычисления суммы всех значений SUM и общего количества значений COUNT. Другими примерами являются справочные таблицы для подстановки одного значения или команды, возвращающие логическое значение. Метод ExecuteScalar выполняет заданную команду и возвращает значение первой записи из первого поля возвращенного набора записей, а все другие поля и записи игнорируются.

Включим приведенную ниже хранимую процедуру в базу данных pubs.

CREATE PROCEDURE AuthorsInState2
SELECT count(*) FROM authors WHERE state = @param1

Хранимая процедура AuthorsInState2 принимает параметр, который имеет двухсимвольный код штата, и возвращает из таблицы authors количество авторов из этого штата. Эта процедура с функциональной точки зрения эквивалентна процедуре AuthorsInState1 из листинга 4.5, но возвращает вычисленное значение для набора записей, а не только индикатор успешности выполнения команды.

НА ЗАМЕТКУ

Использование метода ExecuteScalar вместо метода ЕxecuteNonQuerу и передача скалярного значения с помощью параметра ReturnValue связаны с дополнительными накладными расходами. Зачем же его используют? Он проще в употреблении, потому что не нужно заботиться об указании параметров в определениях и вызовах команд.

Для вызова данной хранимой процедуры с помощью провайдера данных ODBC выполните следующее.

1. Создайте дополнительную кнопку под текстовым полем txtParam1.

2. В окне свойств Properties укажите значение cmdScalar для свойства (Name) и значение ExecuteScalar для свойства Text.

3. Создайте код подпрограммы btnExecuteScalar_Click, приведенный в листинге 4.7.

Листинг 4.7. Код извлечения скалярного значения из хранимой процедуры с помощью провайдера данных ODBC
Private Sub btnExecuteScalar_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnExecuteScalar.Click
" Создание экземпляра объекта Connection.
Dim cnn As OdbcConnection = New OdbcConnection(_
"DRIVER={SQL Server};server=localhost;uid=sa;database=pubs")
" Создание экземпляра объекта Command.
Dim cmd As OdbcCommand = New OdbcCommand()
" Указание подключения и текста команды.
cmd.CommandType = CommandType.StoredProcedure
cmd.CommandText = "{call AuthorsInState2(?) }"
" Создание параметра и указание его значения
cmd.Parameters.Add("@param1", OdbcType.Char, 2)
cmd.Parameters("@param1").Value = txtParam1.Text
MessageBox.Show("Count is " & result, "DataProviderObjects")

Запустите приложение и введите в текстовом поле над кнопкой ExecuteScalar двухсимвольный код штата. После щелчка на кнопке ExecuteScalar появится диалоговое окно с сообщением о количестве авторов в данном штате. Полученный результат можно проверить с помощью программы SQL Server Enterprise Manager, просматривая данные в таблице authors в базе данных pubs.

НА ЗАМЕТКУ

Учтите, что по умолчанию база данных pubs содержит двух авторов из штата Юта (код UТ) и 15 авторов из штата Калифорния (код СА).

Метод ExecuteReader

Этот метод применяется для возвращения набора записей. В большинстве приложений для работы с базами данных именно он используется чаще всего. Работа этого метода основана на объекте DataReader, с помощью которого записи обрабатываются последовательно одна за другой. Более подробно метод ExecuteReader и объект DataReader рассматриваются в следующем разделе.

Объект DataReader

Данный объект предназначен для чтения в прямом направлении небуферизуемого потока записей, полученных от метода ExecuteReader объекта Command. Объект DataReader в основном эквивалентен объекту Recordset модели ADO 2.X, который также предназначен для чтения в прямом направлении. Объект DataReader предлагает наиболее быстрый способ доступа к источнику данных, но в нем не предусмотрены возможности прокрутки и обновления данных. Поскольку данные не буферизуются и не сохраняются в кэше, этот метод прекрасно подходит для извлечения большого объема данных. Для перехода к следующей записи объекта DataReader нужно вызвать его метод Read.

Кроме коллекции Fields, доступ к полям каждой записи можно осуществить с помощью строго типизированных методов. Доступ к полям с помощью коллекции Fields аналогичен способу доступа к полям в модели ADO 2.X.

НА ЗАМЕТКУ

Объект DataReader не имеет явного конструктора, т.е. его нельзя создать с помощью оператора New(). Для инициализации нового объекта нужно вызвать метод ExecuteReader объекта Command.

Зная тип данных в поле, доступ к нему можно получить с помощью типизированных методов доступа. Эти методы извлекают значение поля по номеру поля, нумерация которого начинается с нуля, например:

В самом первом примере используется имя поля Myfield, что значительно упрощает его чтение, использование и совместимость с унаследованными программами. Во втором примере используется номер поля, что значительно повышает производительность, поскольку исключается преобразование имени поля в его номер.

Для демонстрации способов использования этих методов выполните следующее.

1. Создайте под кнопкой ExecuteScalar дополнительную кнопку.

2. В окне свойств Properties укажите значение cmdExecuteReader для свойства (Name) и значение ExecuteReader для свойства Text.

3. Создайте код подпрограммы btnExecuteReader_Click, приведенный в листинге 4.8.

НА ЗАМЕТКУ

Кроме способов использования объекта DataReader, в этом примере демонстрируются и другие функциональные возможности. Например, здесь помимо членов Text и StoredProcedure свойства-перечисления CommandType для указания типа команды используется член TableDirect. Он содержит имя таблицы, все поля которой возвращаются данной командой. Учтите, что этот член перечисления поддерживается только для провайдера данных ODBC.

Представления обычно обрабатываются точно также, как и таблицы. Следовательно, при использовании члена TableDirect свойства-перечисления CommandType можно указывать не только имя таблицы, но и имя представления.

Листинг 4.8. Код создания объекта DataReader и извлечения значений полей с помощью представления и члена TableDirect
Private Sub btnExecuteReader_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnExecuteReader.Click
" Создание экземпляра объекта Connection.
Dim cnn As OleDbConnection = New OleDbConnection(_
"provider=SQLOLEDB;server=localhost;uid=sa;database=pubs")
" Создание экземпляра объекта Command.
Dim As OleDbCommand = New OleDbCommand()
" Указание подключения и текста команды
cmd.CommandType = CommandType.TableDirect
cmd.CommandText = "EmployeeJobs_View"
" Открытие подключения перед вызовом метода
Dim reader As OleDbDataReader
txtResults.Text = txtResults.Text & reader("fname") & _

(Здесь предполагается, что представление EmployeeJobs_view уже создано с помощью подпрограммы btnNonQuery_Click из листинга 4.4, как описано выше. – Прим. ред.)

НА ЗАМЕТКУ

Перед попыткой доступа к данным объекта DataReader не забывайте вызывать метод Read(). В отличие от объекта Recordset в модели ADO 2.X, в которой после загрузки данных текущее расположение автоматически находится на первой записи, в модели ADO.NET в объекте DataReader нужно явно указать текущее расположение возле первой записи с помощью исходного вызова метода

Для организации доступа к данным можно также применить цикл While с более эффективными строго типизированными методами доступа к полям.

txtResults.Text = txtResults.Text & reader.GetString(1) & _
ControlChars.Tab & reader.GetString(2) & _
ControlChars.Tab & ControlChars.Tab & _
reader. GetString(0) & ControlChars.Ctrlf

Еще одно изменение, которое диктуется личным вкусом и стилем программирования автора, заключается в объединении определения объекта DataReader и выполнения метода ExecuteReader в одной строке, т.е. вместо фрагмента кода

Dim reader As OleDbDataReader reader = cmd.ExecuteReader()

можно использовать следующую строку:

Dim reader As OleDbDataReader = cmd.ExecuteReader()

После запуска приложения DataProviderObjects щелкните на кнопке ExecuteReader, и в текстовом поле справа будут отображены данные из представления EmployeeJobs_view, как показано на рис. 4.4.


РИС. 4.4. Результаты выполнения команды ExecuteReader из листинга 4.8


НА ЗАМЕТКУ

По окончании использования объекта DataReader следует вызвать метод Close. Дело в том, что выходные данные или возвращаемые значения объекта Command недоступны до тех пор, пока объект DataReader открыт. Он остается открытым до тех пор, пока открыто само подключение или объект DataReader.

Объект DataReader также предлагает простой и эффективный способ создания Web-страниц для работы сданными на основе элемента управления DataGrid, который подробно рассматривается в главе 11, "Web-формы: приложения на основе ASP.NET для работы с базами данных".

Использование объектов Connection и Command во время создания приложения

Вкладка Data панели элементов управления среды Visual Studio .NET содержит компоненты, которые соответствуют некоторым методам доступа к данным. С помощью окна Properties они позволяют указывать значения свойств во время создания приложения, а не только во время его выполнения. Они также предлагают визуальные инструменты указания значений для более сложных свойств.

Например, для реализации кода из листинга 4.8 с помощью таких элементов управления выполните перечисленные ниже действия.

1. Создайте еще одну форму Form2 в проекте DataProviderObjects.

2. В окне свойств Properties укажите значение Connection and Command Components для свойства Text формы Form2.

3. Увеличьте размер формы.

4. Включите в форму текстовое поле Textbox1.

5. В окне свойств Properties укажите значение True для свойства Multiline и значение Both для свойства Scrollbars этого текстового поля.

6. Увеличьте размер текстового поля так, чтобы оно покрывало большую часть формы.

7. Из вкладки Data панели элементов управления перетащите элемент управления OleDbConnection в форму Form2. Этот компонент невидим во время выполнения приложения, поэтому он появится в разделе невизуальных компонентов в нижней части окна редактирования формы.

8. В окне свойств Properties укажите приведенное ниже значение для свойства ConnectionString элемента управления OledbConnection1.

provider=SQLOLEDB;server=localhost;uid=sa;database=pubs

9. Из вкладки Data панели элементов управления перетащите еще один элемент управления OleDbCommand в форму Form2. Этот компонент также невидим во время выполнения приложения, поэтому он появится в нижней части окна редактирования формы.

10. В окне свойств Properties укажите значение OledbConnection1 для свойства Connection и приведенное ниже значение для свойства CommandText элемента управления OledbCommand1.

SELECT * FROM EmployeeJobs_view

11. Создайте код подпрограммы Form2_Load, приведенный в листинге 4.9.

СОВЕТ

В главе 6, "ADO.NET: объект DataAdapter" представлены графические инструменты, которые позволяют автоматически создать строку подключения и текст команды SQL вместо создания вручную их кода.

Листинг 4.9. Код создания объекта DataReader и извлечения значений полей с помощью компонентов SqlConnection и SqlCommand
Private Sub Form2_Load(ByVal sender As System.Object, _
" Открытие подключения перед вызовом метода ExecuteReader.
Dim reader = OleDbCommand1.ExecuteReader()
TextBox1.Text = TextBox1.Text & reader("fname") & _
ControlChars.Tab & reader("lname") & _
ControlChars.Tab & ControlChars.Tab & _
reader("job_desc") & ControlChars.CrLf
" Отмена выбора всех строк в текстовом поле.

12. Щелкните правой кнопкой мыши на проекте DataProviderObjects в окне Solution Explorer и выберите команду Properties в контекстном меню.

13. В папке Common Properties выберите элемент General, а затем выберите форму Form2 в текстовом поле Startup object (Объект запуска) данного приложения.

После запуска приложения DataProviderObjects в текстовом поле формы Form2 будут отображены данные из представления EmployeeJobs_view, как показано на рис. 4.5.

Другие провайдеры данных

Выше были представлены классы нескольких основных провайдеров данных (например, Parameter и Parameters), а также четыре основных объекта в табл. 4.1. В главе 5, "ADO.NET: объект DataSet", более подробно рассматривается объект DataSet и связанные с ним объекты, а в главе 6, "ADO.NET: объект DataAdapter", – объект DataAdapter.

В оставшейся части главы рассматривается еще один провайдер данных - объект-транзакция Transaction. Транзакции используются для гарантированного успешного завершения сразу нескольких связанных операций по принципу "все или ничего". Это значит, что либо все операции транзакции успешно выполняются, либо они вообще не выполняются. Классическим примером транзакции является банковская операция перечисления денежных средств. Эта операция состоит из двух этапов: удержание денежной суммы с одного счета и зачисление ее на другой счет. При этом желательно избегать ситуаций, когда успешно выполняется только первый этап транзакции!


РИС. 4.5. Результаты отображения данных в форме Form2 с помощью элементов управления OleDbConnection и OleDbCommand


Провайдеры данных ADO.NET содержат объект Transaction, который имеет фундаментальные методы обработки транзакций. Метод Commit фиксирует текущую транзакцию, а метод Rollback – откатывает (отменяет) текущую транзакцию. Выполнение транзакции и создание объекта Transaction осуществляется с помощью вызова метода BeginTransaction по отношению к открытому объекту Connection. Способ использования объекта Transaction демонстрируется на примере бизнес-ситуации 4.1.

Бизнес-ситуация 4.1: создание процедуры для архивирования старых заказов по годам

После относительно длительного использования системы управления базами данных некоторые данные рекомендуется архивировать. В каждой рабочей системе операцию архивирования следует включить в состав обязательных и регулярно выполняемых операций резервного копирования. Архивируемые данные - это данные, которые нужны не для постоянного использования (т.е. в оперативном режиме), а только изредка. Удаление этих данных из основных оперативных таблиц базы данных может повысить производительность операций доступа к этим таблицам, так как при этом приходится обрабатывать и фильтровать меньше записей. Однако архивная таблица часто хранится в идентичном формате таблицы и доступ к ней в случае необходимости можно организовать аналогичным образом. В этой бизнес-ситуации создается простая форма для выполнения простого архивирования данных из таблицы tblOrder базы данных Novelty. Она позволит выбирать и архивировать заказы по годам, т.е. после выбора нужного года выполняются перечисленные ниже действия.

1. Сначала в базе данных создается новая таблица tblOrderXXXX, где ХХХХ обозначает тот год, записи о заказах которого будут архивироваться.

2. Затем все записи о заказах за указанный год копируются из таблицы tblOrder втаблицу tblOrderXXXX.

3. Все скопированные записи о заказах за указанный год удаляются из таблицы tblOrder.

Хитрость здесь заключается в том, чтобы отменить всю транзакцию при неудачном выполнении какой-либо ее операции. Нам не нужна новая таблица, если в нее нельзя скопировать данные. Не нужно архивировать данные, если они не удаляются из основной таблицы. Аналогично, не нужно удалять никакие записи из основной таблицы, если они не скопированы в архивную таблицу. Для решения этой задачи можно использовать объект Transaction и вернуть (откатить) базу данных в исходное состояние в случае сбоя каких-то операций. Для создания формы с этими функциями выполните перечисленные ниже действия.

Запустите интегрированную среду разработки Visual Studio .NET.

2. Создайте новый проект Visual Basic Windows Application.

3. Назовите проект BusinessCase4.

4. Укажите путь к файлам проекта.

5. Увеличьте размер формы Form1.

6. В окне Properties укажите значение frmArchive для свойства (Name) и значение Archive Orders для свойства Text формы Form1.

7. Создайте в форме поле со списком lstYears, надпись Label1, кнопку bntOK и кнопку btnCancel, перетаскивая их из панели элементов управления.

8. В окне Properties укажите значение Archive all orders for the year для свойства Text надписи, значение OK для кнопки btnOK и значение Cancel для кнопки btnCancel.

9. Расположите все элементы управления, как показано на рис. 4.6.

РИС. 4.6. Расположение элементов управления в форме frmArchive


В верхней части файла с исходным кодом вставьте приведенную ниже строку кода для импорта пространства имен SqlClient.

В теле определения класса для формы frmArchive включите код из листинга 4.10.

Листинг 4.10. Код архивирования данных в новой таблице
Private Sub frmArchive_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
" Указание значения по умолчанию.

Private Sub btnCancel_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnCancel.Click

Private Sub btnOK_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnOK.Click
" Создание экземпляров объектов Connection и Command.
Dim cnn As SqlConnection = New SqlConnection(_
"server=localhost;uid=sa;database=novelty")
" Получение значения года.
SelectedYear = lstYears.SelectedItem.ToString
" Размещение кода внутри блока Try-Catch для
" обработки исключительных ситуаций.
" Открытие объекта Connection и запуск транзакции.
" Включение команды в транзакцию.
" Указание команды SQL для вставки соответствующих
" записей в архивную таблицу.
sql = "SELECT * INTO tblOrder" & SelectedYear & _
FROM tblOrder WHERE year (OrderDate) = " & SelectedYear
" Передача текста команды SQL в транзакцию.
result = cmd.ExecuteNonQuery()
" Отображение результатов вставки записей в архивную таблицу.
records = result MessageBox.Show(records & _
" records inserted successfully into tblOrder" & SelectedYear)
"No records inserted into tblOrder" & SelectedYear)
" При отсутствии записей созданная таблица
" не нужна и транзакцию нужно откатить.
" Команда SQL для удаления соответствующих
" записей из текущей таблицы.
sql = "delete FROM tblOrder WHERE year (OrderDate) = " _
" Эта команда находится в той же транзакции.
result = cmd.ExecuteNonQuery()
" Показать результаты удаления записей.
" records deleted successfully")
" Все действия успешно выполнены, можно фиксировать транзакцию.

Подпрограмма btnCancel_Click обработки щелчков мышью на кнопке Cancel просто закрывает форму, что в данном случае приводит к закрытию программы. Все необходимые действия выполняются обработчиком щелчков мышью на кнопке OK. После объявлений переменных следует получить выбранный год из списка lstYears и сохранить его для дальнейшего использования. Для гарантированной отмены транзакции в случае возникновения любой исключительной ситуации следует окружить активный код блоком Try-Catch-Finally.

Поскольку транзакции определяются на уровне подключения, то сначала нужно открыть подключение, а затем создать объект Transaction с помощью вызова метода BeginTransaction для открытого подключения. Объекты Connection и Transaction присваиваются объекту Command, который будет использоваться для выполнения команд по отношению к базе данных.

Первые два этапа создания архивной таблицы и копирования выбранных строк выполняются с помощью одной команды SELECT, которая содержит предложение INTO имя_таблицы. Указанная таким образом таблица создается автоматически, а если такая таблица уже существует, то генерируется исключительная ситуация. Выбранное значение года добавляется к имени таблицы tblOrder для создания имени новой архивной таблицы.

НА ЗАМЕТКУ

Команда SELECT INTO не создает индекс, если он существует в исходной таблице. Для повышения производительности выполнения запросов по отношению к данной таблице, вероятно, придется создать индексы по одному или нескольким полям.

Для выполнения команды SQL вызывается метод ExecuteNonQuery, который возвращает количество охваченных запросом записей. Если это возвращаемое значение больше нуля, следовательно, нужные записи найдены и вставлены в новую таблицу. В противном случае это значит, что таблица не может быть создана либо для копирования не найдено никаких записей. В любом из этих двух случаев транзакция откатывается, даже если таблица создана, чтобы база данных не наполнялась пустыми и бесполезными таблицами.

Если хотя бы одна запись скопирована в таблицу, то ее прототип в исходной таблице tblOrder удаляется с помощью команды DELETE, содержащей предложение WHERE с заданным годом. В случае успешного выполнения этой команды, т.e. если количество скопированных и удаленных строк совпадает, транзакция считается успешно завершенной и фиксируется. В противном случае, т.е. если какая-то отдельная операция завершится неудачно (нарушится процесс удаления записей, будет отменено разрешение на удаление архивируемых данных или произойдет сбой сервера), вся транзакция будет отвергнута. Откат транзакции гарантирует, что при неудачной попытке удаления корректных записей из таблицы tblOrder архивная таблица tblOrderХХХХ будет удалена.

До сих пор рассматривались только те исключительные ситуации, которые возникают при нарушении последовательного выполнения операций подпрограммы. Однако следует также позаботиться о многих других исключительных ситуациях, которые могут возникнуть во время выполнения. Например, исключительная ситуация может возникнуть при попытке создания уже существующей таблицы. Для ее перехвата и обработки следует использовать блок Try-Catch, который в данном случае выводит текстовое сообщение об исключительной ситуации, а вся транзакция отвергается.

НА ЗАМЕТКУ

Еще один блок Try-Catch потребуется для обработки исключительной ситуации, когда архивная таблица не может быть создана (например, из-за наличия именно такой таблицы). Основная причина, по которой она предлагается, заключается в том, что транзакция началась, но никаких изменений данных не произошло, а потому в файл регистрации транзакций не записано никаких действий, которые нужно откатить.

В блоке Finally используемое подключение закрывается независимо от того, произошла или нет исключительная ситуация.

Выполните все описанные выше действия и поэкспериментируйте с этим приложением, создавая архивы для записей разных лет. Для проверки полученных результатов сопоставьте содержимое новой архивной и исходной таблиц до и после архивирования. Не забывайте, что содержимое исходной таблицы tblOrder всегда можно вернуть в первоначальное состояние, запуская сценарий ее создания и наполнения данными.

Резюме

В этой главе приводятся общие сведения об ADO.NET и некоторых объектах провайдеров данных.NET. Провайдеры данных образуют интерфейс ADO.NET для взаимодействия с физическими хранилищами данных и предлагают модель программирования в режиме подключения. Здесь кратко рассматриваются свойства и методы объектов Connection, Command, Parameter, DataReader и Transaction, включая стандартные провайдеры данных SqlClient, OleDb и Odbc. В главе 5, "ADO.NET: объект DataSet", описываются способы работы с данными в отключенном режиме на основе объектов DataSet и DataAdapter.

Вопросы и ответы

Судя по содержанию этой главы, модель ADO.NET предназначена для работы в отключенном режиме и нет никакой поддержки для серверных курсоров или пессимистической блокировки. А что же делать, если уже существующее приложение использует их или спецификации нового проекта требуют их применения? Следует ли мне использовать для этого только Visual Basic 6.0?

Во-первых, необходимо тщательно проанализировать приложение и убедиться в том, что действительно всегда нужно использовать серверные курсоры или пессимистические блокировки. Если они (или какие-то другие компоненты, которые не поддерживаются в ADO.NET) действительно необходимы, не стоит отчаиваться. Visual Basic. NET все равно можно использовать для таких приложений, так как на платформе.NET Framework предусмотрена расширенная поддержка взаимодействия с COM, что позволяет использовать в.NET-совместимом приложении COM-объекты, которые, в свою очередь, могут использовать управляемый (.NET-совместимый) код. Иначе говоря, можно использовать не только ADO 2.X, но и любые другие COM-объекты, для которых нет аналогов в.NET. Конечно, за организацию взаимодействия между COM и.NET придется заплатить снижением производительности. В какой мере? Ответ на этот вопрос можно получить только после тщательного тестирования приложения.

Похоже, что программирование объектов, методов и свойств ничем не отличается от способов их программирования в модели ADO 2.X. Зачем же переходить к модели ADO.NET?

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

1. Visual Basic .NET и платформа.NET представляют собой совершенно новый мир, а модель ADO.NET является способом доступа к данным в этом мире.

2. Хотя при создании.NET-совместимых приложений можно продолжать использование уже существующих COM-компонентов, например из модели ADO 2.X, такой способ связан с сокращением производительности при доступе к COM-компонентам и необходимости их корректной инсталляции и регистрации.

3. Рассмотренные в этой главе объекты разных провайдеров данных отвечают только за часть всех операций с базой данных, а именно за чтение и запись данных в подключенном режиме. Другая часть операций выполняется в отключенном режиме и связана с объектом DataSet. Именно в этом режиме прекрасно проявляются преимущества модели ADO.NET, и потому в следующей главе описываются базовые блоки объекта DataSet.


Центр обработки и хранения данных под ключ от компании

Событие возникает перед выполнением команды. Параметры:
  • Source - строка, содержащая оператор SQL или имя хранимой процедуры.
  • CursorType - тип курсора для Recordset, который будет открыт. Тип курсора можно изменять. Возможные значения:
    • adOpenUnspecified(-1) - тип курсора не определён.
    • adOpenForwardOnly(0) - определяет forward-only курсор. То же, что и статический курсор, но вы можете прокручивать записи только вперед. Это оптимизирует выполнение, если вы должны сделать только один проход по Recordset"у.
    • adOpenKeyset(1) - Определяет keyset-курсор. То же, что и динамический курсор, но вы не можете видеть записи, добавляемые другими пользователями, хотя записи, удаляемые другими пользователями, недоступны в вашем Recordset"е. Изменения данных другими пользователями видимы.
    • adOpenDynamic(2) - Определяет динамический курсор. Добавления, изменения и удаления другими пользователями видимы; разрешены все типы движения через Recordset, исключая закладки, если провайдер их не поддерживает.
    • adOpenStatic(3) - Определяет статический курсор. Статическая копия набора записей, которую вы можете использовать, чтобы найти данные или генерировать отчёты. Добавления, изменения или удаления другими пользователями не видимы.
  • LockType - тип блокировки для Recordset, который будет открыт. Возможные значения:
    • adLockUnspecified(-1) - тип блокировки не определён.
    • adLockReadOnly(1) - только для чтения. Вы не можете изменить данные.
    • adLockPessimistic(2) - пессимистическая блокировка. Провайдер гарантирует успешное редактирование записей. Запись блокируется сразу после начала редактирования и до момента сохранения записей.
    • adLockOptimistic(3) - оптимистическая блокировка. Провайдер осуществляет блокировку записей только в момент сохранения изменений, т.е. когда вы вызываете метод Update().
    • adLockBatchOptimistic(4) - оптимистические пакетные модификации. Требуется для пакетного режима модификации (отложенное сохранение записей).
  • Options - целое число (long), указывающее опции выполнения команды или открытия Recordset"а.
  • adStatus - определяет состояние события. Возможные значения - см. описание аналогичного параметра события ConnectComplete.
  • pCommand - объект Command, для которого применяется это событие.
  • pRecordset - объект Recordset, для которого применяется это событие.
  • pConnection - объект Connection, для которого применяется это событие.
Событие WillExecute может произойти из-за вызовов Connection.Execute, Command.Execute, или Recordset.Open. Параметр pConnection всегда содержит ссылку на объект Connection. Если событие происходит из-за вызова Connection.Execute, параметры pRecordset и pCommand будут установлены в Nothing. Если событие происходит из-за вызова Recordset.Open, параметр pRecordset будет содержать ссылку на объект Recordset, а параметр pCommand будет установлен в Nothing. Если событие происходит из-за вызова Command.Execute, параметр pCommand будет содержать ссылку на объект Command, а параметр pRecordset будет установлен в Nothing.

В ADO.NET используется многоуровневая архитектура, которая обращается вокруг небольшого числа ключевых концепций, таких как объекты Connection, Command и DataSet. Однако архитектура ADO.NET серьезно отличается от классической архитекуры ADO.

Поставщики данных в ADO.NET

Поставщик данных (data provider) - это набор классов ADO.NET, которые позволяют получать доступ к определенной базе данных, выполнять команды SQL и извлекать данные. По сути, поставщик данных - это мост между вашим приложением и источником данных.

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

Тип объекта Базовый класс Соответствующие интерфейсы Назначение
Connection DbConnection IDbConnection Позволяет подключаться к хранилищу данных и отключаться от него. Кроме того, объекты подключения обеспечивают доступ к соответствующим объектам транзакций
Command DbCommand IDbCommand Представляет SQL-запрос или хранимую процедуру. Кроме того, объекты команд предоставляют доступ к объекту чтения данных конкретного поставщика данных
DataReader DbDataReader IDataReader, IDataRecord Предоставляет доступ к данным только для чтения в прямом направлении с помощью курсора на стороне сервера
DataAdapter DbDataAdapter IDataAdapter, IDbDataAdapter Пересылает наборы данных из хранилища данных к вызывающему процессу и обратно. Адаптеры данных содержат подключение и набор из четырех внутренних объектов команд для выборки, вставки, изменения и удаления информации в хранилище данных
Parameter DbParameter IDataParameter, IDbDataParameter Представляет именованный параметр в параметризованном запросе
Transaction DbTransaction IDbTransaction Инкапсулирует транзакцию в базе данных

Конкретные имена этих основных классов различаются у различных поставщиков (например, SqlConnection, OracleConnection, OdbcConnection и MySqlConnection), но все эти объекты порождены от одного и того же базового класса (в случае объектов подключения это DbConnection), который реализует идентичные интерфейсы (вроде IDbConnection). Поэтому если вы научитесь работать с одним поставщиком данных, но легко справитесь и с остальными.

В ADO.NET термин "объект подключения" на самом деле относится к конкретному типу, порожденному от DbConnection; объекта подключения "вообще" нет. То же можно сказать и об "объекте команды", "объекте адаптера данных" и т.д. По соглашению имена объектов в конкретном поставщике данных имеют префиксы соответствующей СУБД (например, SqlConnection, OracleConnection, SqlDataReader и т.д.).

55. Технология ASP.NET. Методы доступа к удаленным данным.

56. Объектная модель ASP.NET. Характеристика и назначение основных объектов. Примеры.

57. Компоненты ASP. Примеры использования для доступа к различным источникам данных.

58. Организация пользовательского интерфейса. Передача данных между модулями приложения.

59. Общая характеристика рынка программных продуктов КИС.

60. Анализ рынка программных продуктов КИС

Общая характеристика программных продуктов для КИС компании Oracle

Oracle Database

Программное обеспечение Oracle Database поставляется в различных редакциях, ориентированных на различные сценарии разработки и развертывания приложений. Ниже перечислены существующие редакции СУБД Oracle Database 11g:

· Enterprise Edition

Enterprise Edition обеспечивает наивысшую производительность, доступность, масштабируемость и безопасность, необходимую для таких критически важных приложений уровня организации как:
– оперативная обработка большего объема транзакций (OLTP);
– интенсивно запрашиваемые хранилища данных (Data Warehouse, DSS);
– безопасные и ресурсоемкие Интернет приложения.
Редакция Enterprise Edition содержит все компоненты Oracle Database и может быть расширена за счет приобретения дополнительных опций и пакетов.

· Standard Edition

Предназначена для развертывания в малых и средних компаниях. Данная редакция СУБД обеспечивает простоту использования, высокую мощность и производительность с поддержкой Oracle Real Application Clusters (Oracle RAC) для приложений уровня рабочих групп или отделов, включая Web-приложения.
Standard Edition включает в себя все средства, необходимые для создания критически важных бизнес-приложений.
Однако по сравнению c Enterprise Edition, в Standard Edition недоступен целый ряд продвинутых компонентов и функций для обеспечения наиболее высокого уровня доступности, производительности и безопасности приложений, включая средства по автоматизации процесса администрирования, мониторинга и диагностирования Баз Данных.
Редакция Standard Edition может быть лицензирована только на серверах, максимальная емкость которых – 4 процессорных гнезда (sockets).

· Standard Edition One

Предназначена для приложений масштаба рабочих групп, отдельных подразделений и обладает такими же функциональными возможностями как Standard Edition, но без поддержки Oracle RAC.
Редакция Standard Edition One лицензируется только для серверов, имеющих не более двух процессоров (sockets). При этом клиент получает тот же самый код, что и в Standard Edition.

· Personal Edition

Personal Edition доступна только для платформы Windows и поддерживает развертывание однопользовательского приложения, полностью совместимого с редакцией Enterprise Edition, за исключением того, что отсутствует Oracle RAC.

Что такое лицензия Oracle.

Распространение программных продуктов Oracle (далее «Программы») осуществляется путем предоставления лицензий на их использование.
Лицензия – это неисключительное, бессрочное и непередаваемое право на использование Программ, предоставляемое Конечному Пользователю на условиях компании Oracle. Авторские права и права собственности на лицензируемые программные продукты сохраняются за компанией-производителем.
Лицензирование Программ означает приобретение прав на их использование, а не покупку самих программных продуктов.
Стоимость лицензии не зависит от версии программного обеспечения Oracle (8i, 9i, 10g, 11g) и платформы (Windows, Linux, Unix и т.д.).
В тоже время, только клиенты, которые в настоящее время обладают действующей Лицензией на обновление программного обеспечения и поддержку, имеют право на новые версии продуктов.
Лицензируемые Программы предоставляются по каналам электронной связи или на носителях CD-ROM.
Продажа лицензий в странах СНГ производится только уполномоченными партнерами компании Oracle.
У заказчика есть возможность выбрать способ приобретения лицензии: по пользователям – Named User Plus или по процессорам – Processor.

Лицензия на обновление программного обеспечения Oracle и поддержку
(Software Update License & Support)

Лицензия на обновление программного обеспечения и поддержку (далее Software Update License & Support) предоставляет клиентам право на обновление (далее Upgrade) продукта и техническую поддержку в режиме 24x7 в течение пяти лет со дня выпуска продукта.
Upgrade продукта включает в себя обновление версий программного обеспечения, техническое обслуживание релизов и предоставление патчей (исправлений).
Клиенты получают прямой доступ к специалистам Oracle по конкретным вопросам, касающимся установки и эксплуатации программного обеспечения Oracle.

Web-поддержка осуществляется через My Oracle Support (бывший OracleMetaLink).
My Oracle Support обеспечивает клиентов про-активными (заблаговременными) уведомлениями, настраиваемой домашней страницей, техническими библиотеками и форумами, информацией о жизненном цикле продукта, базой данных ошибок (bug) и возможностью отправить Технический запрос на обслуживание (SR – Service Request).
Software Update License & Support предоставляется в течение одного года и приобретается одновременно с Лицензиями на продукты Oracle.
Стоимость Software Update License & Support составляет 22% от стоимости приобретенных Лиценз на продукты Oracle.

Продление поддержки
(Support Renewals)

Software Update License & Support продлевается путем внесения ежегодной абонентской платы.
Регулярное ежегодное продление Software Update License & Support обеспечивает оптимизацию расходов по обновлению продуктов Oracle в последующие периоды.

Лицензионные метрики
(License Metrics)

Как правило, программные продукты Oracle лицензируются с помощью одной из наиболее часто используемых метрик:

  • Named User Plus (Именованный пользователь)

С помощью метрики Named User Plus (NUP) лицензируются так называемые именованные пользователи.
Именованный пользовател ь – лицо, уполномоченное использовать Программы, установленные на одном или нескольких серверах, не зависимо от того, использует ли оно программу в данный момент времени или нет. Автоматическое устройство (не требующее участия человека) при возможности доступа к Программам считается пользователем (NUP) в дополнение ко всем лицам, уполномоченным использовать Программы.
При использовании мультиплексирующих аппаратных или программных средств (например, монитора транзакций или веб-сервера) это число должно быть определено на входе мультиплексора.

ADO.NET представляет собой набор библиотек, входящих в Microsoft .NET Framework и предназначенных для взаимодействия с различными хранилищами данных из.NET-приложений. Библиотеки ADO.NET включают все необходимые классы для подключения к источникам данных практически произвольного формата, выполнения запросов к этим источникам и получения результата. Кроме того, несомненным достоинством ADO.NET является возможность работы с отсоединенными источниками данных, представляющими собой структуры, которые организуют данные в оперативной памяти компьютера и работать с которыми возможно с использованием ставших уже привычными средств доступа к данным. Таким образом, ADO.NET можно использовать в качестве надежного, иерархически организованного отсоединенного от источника кэша данных для автономной работы, что незаменимо при построении масштабируемых приложений, особенно ориентированных на Web.

На сегодняшний день ADO.NET является наиболее развитой технологией доступа к данным среди технологий, разработанных корпорацией Microsoft. Она развивает те принципы, которые были заложены в таких технологиях, как DAO и ADO, делая их более простыми в применении, более мощными и универсальными. В то же время ADO.NET является уже иной технологией доступа к данным.

Рассмотрим архитектуру ADO.NET

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

На рис. 10.1 показаны классы, составляющие объектную модель ADO.NET

Рис. 10.1. Иерархия объектов ADO.NET

Объекты, расположенные в левой части, называются подсоединенными и необходимы для управления соединением, транзакциями, выборкой данных и передачей изменений данных в БД. Они непосредственно взаимодействуют с базой данных. Объекты, расположенные в правой части, называются отсоединенными. Они позволяют работать с данными автономно. Отсоединенные объекты не взаимодействуют непосредственно с подсоединенными для получения данных из БД. Точнее, можно сказать, что они не взаимодействуют со всеми объектами левой части иерархии объектов. И хотя вопросы заполнения данными отсоединенных объектов будут обсуждаться позднее, можно сказать, что одной из форм взаимодействия этих двух групп является использование объектом DataAdapter объекта DataSet для заполнения последнего набором данных, извлеченных непосредственно из БД.

Одной из основных идей, лежащих в основе ADO.NET, является наличие поставщиков данных.

Поставщик данных - это набор классов, предназначенных для взаимодействия с хранилищем данных определенного типа. За счет этого модель ADO.NET является чрезвычайно гибкой и расширяемой. Рассмотрим уровни модели поставщиков ADO.NET (рис. 10.2).


Рис. 10.2. Уровни моделей поставщиков ADO.NET

Как видно из рис. 10.2, приложение.NET взаимодействует с базой данных посредством поставщиков данных. Каждый поставщик данных может обеспечивать доступ только к базе данных определенного формата. Так, для доступа к БД Microsoft SQL Server используется поставщик SQL Server для.NET, для доступа к БД Oracle - поставщик Oracle для.NET и т. д. Названные базы данных являются одними из самых распространенных во всем мире, поэтому поставщики данных для них выделены в отдельные элементы модели ADO.NET ; тем не менее существует множество баз данных другого формата, к которым необходимо осуществлять доступ из приложения.NET. Для этого могут применяться поставщики данных OleDb для.NET или ODBC для.NET, обеспечивающие доступ к любым данным, для которых существует драйвер OleDb либо ODBC соответственно.

При построении приложения, использующего доступ к данным, необходимо сперва попытаться найти "родного" поставщика данных для.NET. Когда же такового не существует, можно воспользоваться OleDb, если существует соответствующий драйвер для источника данных, к которому устанавливается подключение. Т. к. технология OleDb существует достаточно давно, создано много драйверов для различных источников данных, поддерживающих ее. Если в системе не установлен соответствующий драйвер OleDb, его можно попытаться найти на сайте разработчика той базы данных, к которой осуществляется доступ, либо на сайте Microsoft. То же самое справедливо и для технологии ODBC. В ряде случаев существует несколько альтернативных вариантов организации доступа к данным определенного формата. Например, доступ к источнику данных на основе SQL Server можно организовать используя либо поставщик SQL Server для.NET, либо поставщик OleDb. Тем не менее всегда предпочтительнее использовать тот поставщик данных, который специально предназначен для обеспечения доступа к конкретному источнику данных, т. к. он учитывает его особенности.

Каждый поставщик.NET реализует одинаковые базовые классы - Connection, Transaction, DataAdapter, Command, Parameter, DataReader имена которых зависят от поставщика. Например, у поставщика SQL Server существует объект SqlDataAdapter, у поставщика OleDb - OleDbDataAdapter и т. д.

У каждого поставщика данных существует собственное пространство имен. Хотя все поставщики относятся к пространству имен System.Data, каждый из них содержит свой подраздел этого пространства, который содержит объекты, специфичные для данного поставщика. Например, объект SqlDataAdapter находится в пространстве имен System.Data.SqlClient.

Все поставщики данных.NET реализуют одинаковые базовые функции, поэтому код, создаваемый для доступа к данным, выглядит приблизительно одинаково независимо от поставщика. Это означает, что, рассматривая использование интерфейсов отдельного поставщика, мы фактически рассматриваем возможность использования этих же интерфейсов применительно и к другим поставщикам данных.

При организации доступа к данным с помощью ADO.NET исключительно важную роль играют объекты, изображенные на рис. 10.1. Рассмотрим их более подробно.

Объект Connection представляет соединение с источником данных. С его помощью можно задать тип источника данных, его местонахождение, параметры доступа и ряд других атрибутов. Перед тем как начать взаимодействие с источником данных, необходимо установить подключение к нему с помощью объекта Connection.

Объект Command представляет запрос к источнику данных, вызов хранимой процедуры или прямой запрос на возврат содержимого конкретной таблицы. Как известно, существует несколько типов запросов. Часть из них возвращают данные, извлекаемые из источника данных, другие изменяют записи, третьи - управляют структурой БД. С помощью объекта Command возможно выполнить любой из перечисленных типов запросов. Различия в поведении объекта Command начинают проявляться тогда, когда необходимо исполнить тот или иной запрос. Так, например, при необходимости исполнения запроса, не возвращающего записи, необходимо использовать метод ExecuteNonQuery объекта Command, а при извлечении данных из БД - метод ExecuteReader, который, в свою очередь, возвращает объект DataReader, позволяющий просматривать полученные в результате запроса записи.

Объект DataReader предназначен для максимально быстрой выборки и просмотра возвращаемых запросом записей. Однако он позволяет просматривать весь результирующий набор записей путем перемещения от одной записи к другой и, таким образом, просматривать только одну запись за раз. Кроме того, DataReader не имеет возможности для обновления значений записей и поэтому может работать в режиме "только для чтения", за счет чего обладает высокой производительностью.

Объект Transaction позволяет осуществлять группировку записей в логическую единицу работы, называемой транзакцией. Транзакция логически объединяет несколько различных действий, связанных с манипулированием данными, в единое целое. В процессе выполнения действий, осуществляемых в рамках транзакции, СУБД обычно кэширует изменения, вносимые этими действиями в данные до момента завершения транзакции. Это позволяет производить отмену любых изменений, выполненных в рамках транзакции, в случае, если хотя бы одно из действий транзакции завершилось неудачно.

Объект Parameter позволяет вводить в запрос элемент, значение которого может быть задано непосредственно перед исполнением запроса. За счет этого отпадает необходимость каждый раз изменять текст самого запроса.

Объект DataAdapter представляет собой связующее звено между отсоединенными объектами ADO.NET и базой данных. С его помощью осуществляется заполнение таких объектов, как DataSet или DataTable, значениями, полученными в результате выполнения запроса к базе данных, для последующей автономной работы с ними. Помимо этого DataAdapter реализует эффективный механизм выполнения обновления данных, хранимых в базе данных, изменениями, внесенными в данные объектов DataSet и DataTable.

Объект DataTable позволяет просматривать данные в виде наборов записей и столбцов. Фактически, он представляет собой аналог таблицы БД, размещенный в памяти. Достоинством такой организации является возможность автономной работы с данными. Это означает, что после установления соединения с базой данных, чтения данных и заполнения ими объекта DataTable можно отключиться от источника данных и продолжать работать с ним в автономном режиме. Такая возможность чрезвычайно полезна при организации Web-приложений, которые должны быть хорошо масштабируемыми и ориентированы на многопользовательский режим работы. При этом, однако, возникают и побочные эффекты, один из которых связан с тем, что человек, работающий с автономным набором данных, не может увидеть изменений, вносимых в данные в этот момент другими пользователями.

Объект DataColumn представляет собой столбец объекта DataTable. Набор же всех столбов объекта DataTable представляет собой коллекцию Columns. Посредством этого объекта можно получить доступ к значению ячейки соответствующего столбца.

Объект DataRow представляет собой строку объекта DataTable. Набор всех строк этого объекта представляет собой коллекцию Rows. DataRow очень часто используется для доступа к значению конкретного поля определенной записи. При этом применяется свойство Item.

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

Объект DataRelation представляет собой описание связей между таблицами реляционной базы данных. Он предоставляется объектом DataSet и позволяет организовывать взаимосвязи между таблицами отсоединенного набора данных объекта DataSet. Объект DataRelation выполняет функцию, аналогичную той, которую выполняют связи, определяемые в СУБД между таблицами при создании структур данных. Это касается и соблюдения принципов ссылочной целостности информации. Например, DataRelation можно настроить таким образом, чтобы изменения значения первичного ключа родительской таблицы автоматически передавались (каскадировались) дочерним записям, а при удалении записи в родительской таблице автоматически удалялись записи в дочерних таблицах, связанных с ней.

Объект DataView предназначен для организации возможности просмотра содержимого DataTable различными способами. Это относится к таким операциям, как сортировка и фильтрация записей. С помощью DataView допускается просматривать содержимое одного объекта DataTable с различными установками фильтрации и сортировки. Для этого необходимо использовать два различных объекта DataView, связанных с одним объектом DataTable. Такая возможность исключает необходимость хранения одного набора данных в двух разных структурах.

Более подробно использование всех объектов модели ADO.NET будет рассмотрено ниже.

Последнее обновление: 31.10.2015

Сегодня большое значение имеет работа с данными. Для хранения данных используются различные системы управления базами данных: MS SQL Server, Oracle, MySQL и так далее. И большинство крупных приложений так или иначе используют для хранения данных эти системы управления базами данных. Однако чтобы осуществлять связь между базой данных и приложением на C# необходим посредник. И именно таким посредником является технология ADO.NET.

ADO.NET предоставляет собой технологию работы с данными, которая основана на платформе.NET Framework. Эта технология представляет нам набор классов, через которые мы можем отправлять запросы к базам данных, устанавливать подключения, получать ответ от базы данных и производить ряд других операций.

Причем важно отметить, что систем управления баз данных может быть множество. В своей сущности они могут различаться. MS SQL Server, например, для создания запросов использует язык T-SQL, а MySQL и Oracle применяют язык PL-SQL. Разные системы баз данных могут иметь разные типы данных. Также могут различаться какие-то другие моменты. Однако функционал ADO.NET построен таким образом, чтобы предоставить разработчикам унифицированный интерфейс для работы с самыми различными СУБД.

Основу интерфейса взаимодействия с базами данных в ADO.NET представляет ограниченный круг объектов: Connection, Command, DataReader, DataSet и DataAdapter. С помощью объекта Connection происходит установка подключения к источнику данных. Объект Command позволяет выполнять операции с данными из БД. Объект DataReader считывает полученные в результате запроса данные. Объект DataSet предназначен для хранения данных из БД и позволяет работать с ними независимо от БД. И объект DataAdapter является посредником между DataSet и источником данных. Главным образом, через эти объекты и будет идти работа с базой данных.

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

По умолчанию в ADO.NET имеются следующие встроенные провайдеры:

    Провайдер для MS SQL Server

    Провайдер для OLE DB (Предоставляет доступ к некоторым старым версиям MS SQL Server, а также к БД Access, DB2, MySQL и Oracle)

    Провайдер для ODBC (Провайдер для тех источников данных, для которых нет своих провайдеров)

    Провайдер для Oracle

    Провайдер EntityClient. Провайдер данных для технологии ORM Entity Framework

    Провайдер для сервера SQL Server Compact 4.0

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

Основные пространства имен, которые используются в ADO.NET:

    System.Data: определяет классы, интерфейсы, делегаты, которые реализуют архитектуру ADO.NET

    System.Data.Common: содержит классы, общие для всех провайдеров ADO.NET

    System.Data.Design: определяет классы, которые используются для создания своих собственных наборов данных

    System.Data.Odbc: определяет функциональность провайдера данных для ODBC

    System.Data.OleDb: определяет функциональность провайдера данных для OLE DB

    System.Data.Sql: хранит классы, которые поддерживают специфичную для SQL Server функциональность

    System.Data.OracleClient: определяет функциональность провайдера для баз данных Oracle

    System.Data.SqlClient: определяет функциональность провайдера для баз данных MS SQL Server

    System.Data.SqlServerCe: определяет функциональность провайдера для SQL Server Compact 4.0

    System.Data.SqlTypes: содержит классы для типов данных MS SQL Servera

    Microsoft.SqlServer.Server: хранит компоненты для взаимодействия SQL Server и среды CLR

Схематично архитектуру ADO.NET можно представить следующим образом:

Функционально классы ADO.NET можно разбить на два уровня: подключенный и отключенный. Каждый провайдер данных.NET реализует свои версии объектов Connection, Command, DataReader, DataAdapter и ряда других, который составляют подключенный уровень. То есть с помощью них устанавливается подключение к БД и выполняется с ней взаимодействие. Как правило, реализации этих объектов для каждого конкретного провайдера в своем названии имеют префикс, который указывает на провайдер:

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