Главная » Microsoft SQL Server, Базы данных » Основы создания приложений

0

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

?               программный код, использующий для взаимодействия с SQL Server первичную interop-сборку .NET adodb .dll;

?               программный код, использующий SqlClient для выполнения эквивалентной операции;

?               код, демонстрирующий доступ с помощью SQL Native Client и обобщенных базовых классов.

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

Здесь мы уделим мало внимания проектированию графического интерфейса, XML и удаленной работе в среде .NET Framework. Конструктор Windows Forms, ASP.NET, SOA и удаленный доступ — очень обширные вопросы, требующие больше места, чем им может быть отведено в настоящей книге. В этом разделе будут продемонстрированы методы перемещения информации в источник данных и из него, а также методы работы с компонентами ADO.NET. Основной нашей целью было показать, насколько просто и изящно можно перемещать информацию с уровня приложения на уровень данных и в обратном направлении. Что будет впоследствии происходить с данными, к которым получен доступ, пусть решит сам разработчик.

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

Примеры программ, приведенные в настоящей главе, можно загрузить с Web- в сайта книги. В этом коде использовано консольное приложение для демонстра- ^^Сети ции нижеописанных методик.

Подключение к SQL Server

Простейшим способом создания подключения является использование мастера конфигурирования источника данных. Выберите в меню Visual Studio команду Data^Add New Data Source или просмотрите источники данных, ассоциированные с существующим проектом приложения, выбрав в меню пункт Data^Show Data Sources.

Не сложнее определить строку подключения и программным путем. Строка подключения представляет собой набор пар “имя-значение”. Единственное, что несколько усложняет ситуацию, — это то, что строки подключения у разных поставщиков .NET несколько отличаются, а подключение ADO вообще стоит в стороне.

В среде .NET Framework 2.0 строки подключения более гибкие, чем в предыдущих Совет       версиях. Например, в строках подключения поставщика ADODB.dll или SNAC

разрешено называть SQL Server и как “Data Source”, и как “Server”.

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

Адаптеры данных

Мастер конфигурирования источника данных позволяет задать таблицы, представления, хранимые процедуры и функции, которые будут использованы для создания набора данных DataSet, как типизированного, так и нетипизированного. В качестве альтернативы набор данных DataSet может быть добавлен в проект и определен в Solution Explorer. В последнем случае в проекте откроется окно Dataset Designer.

Для определения источника данных и набора данных приложения окно Dataset Designer позволяет использовать Server Explorer и панель инструментов. Инструмент Dataset Designer реализует еще один отличный способ создания наборов данных, гарантирующий создание только типизированных наборов. Сторонники “чистого” программирования могут при желании вводить вручную определения типизированных наборов данных, хотя вряд ли для использования такого подхода найдутся достаточные объяснения.

Вспомним, что типизированный набор данных DataSet позволяет избежать проникновения в код ошибок преобразования данных в процессе выполнения приложения. Если вы собираетесь использовать нетипизированный набор DataSet, то нет причин использовать и Dataset Designer. Все, что в данном случае нужно, — это объявить новый, пустой объект DataSet перед тем, как он будет заполняться с помощью заданного объекта адаптера DataAdapter:

1           заполнение нетипизированного набора данных из адаптера Dim daScrapReasons As SqlDataAdapter = _

New SqlDataAdapter(sSQLScrapReasons, cnADONET2)

‘создание нетипизированного набора данных Dim dsWOWithScrap As New DataSet

‘заполнение набора данных из адаптера daScrapReasons.Fill(dsWOWithScrap, "ScrapReason")

Если разработчик выбирает типизированный набор данных, то можно использовать мастер конфигурирования адаптера таблицы (Table Adapter Configuration Wizard) для создания адаптера к каждой из таблиц, определенных в объекте DataSet. Этот мастер запускается из контекстного меню области конструктора Dataset Designer. В этом мастере разработчик может выбрать таблицы базы данных или определить запросы и хранимые процедуры, откуда будут наполняться адаптеры таблиц. Как только способ наполнения таблиц будет определен, мастер автоматически создаст инструкции INSERT, UPDATE и DELETE, которые будут выполняться при вызове в наборе данных метода DataAdapter .Update. Сформированные инструкции можно просмотреть и отредактировать на панели свойств адаптера. Также можно просмотреть и программный код, сформированный на панели конструктора. Редактирование этого кода не рекомендуется, так как любые изменения могут вызвать некорректную работу объекта. В то же время любые изменения, выполненные вручную, будут утеряны, если набор данных или адаптер таблицы будет заново сгенерирован мастером.

Объект чтения данных и наборы записей

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

‘Набор записей из серверного курсора ADO Dim rsADOWOWithScrap As New ADODB.Recordset

rsADOWOWithScrap.CursorLocation = CursorLocationEnum.adUseServer

rsADOWOWithScrap.Open(sSQLWOWithScrap, cnADO,_

CursorTypeEnum.adOpenForwardOnly, _

LockTypeEnum.adLockReadOnly)

‘ Изолированный набор данных из клиентского курсора ADO Dim cmdADOWOWithScrapl As New ADODB.Command Dim rsADOWOWithScrapl As New ADODB.Recordset cmdADOWOWithScrapl.CommandText = sSQLWOWithScrap cmdADOWOWithScrapl.CommandType = _

CommandTypeEnum.adCmdText rsADOWOWithScrapl.CursorType = _

CursorTypeEnum.adOpenStatic rsADOWOWithScrapl.LockType = _

LockTypeEnum.adLockBatchOptimistic rsADOWOWithScrapl.CursorLocation = _

CursorLocationEnum.adUseClient

cmdADOWOWithScrapl.ActiveConnection = cnADO rsADOWOWithScrapl = cmdADOWOWithScrapl.Execute

Объект DataReader модели ADO представляет собой однонаправленный клиентский курсор. Его можно загрузить при необходимости в объект DataTable. Объект DataAdapter содержит методы вставки, обновления и удаления данных объекта DataTable набора данных DataSet и возвращения изменений в базу данных.

Потоки

Данные могут быть направлены в поток и извлечены из него либо в формате XML, либо в двоичном виде. Из-за переходной природы с потоками несколько тяжело работать. В общем случае поток может быть поглощен только единожды, после чего он исчезает:

Dim bfBINWOWithScrap As New Binary.BinaryFormatter Dim msXMLWOWithScrap As New MemoryStream()

Dim msBINWOWithScrap As New MemoryStream()

‘Получение потока XML из набора данных bfBINWOWithScrap.Serialize(msXMLWOWithScrap, _ dsBINWOWithScrap)

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

Асинхронное выполнение

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

Dim rdrAsyncScrapCountlnit As IAsyncResult = _ cmdScrapCount.BeginExecuteReader

‘выполняем другую работу

Dim rdrAsyncScrapCount As SqlDataReader = _

cmdScrapCount.EndExecuteReader(rdrAsyncScrapCountlnit)

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

Использование одного значения из базы данных

Приложения часто интересуют значения только одного или нескольких столбцов строки таблицы. В ADO существовала возможность выполнить запрос и вернуть результат в объект Recordset, имеющий одну строку и один столбец. Также было возможно выполнить инструкцию с выходными параметрами, определенными в ее коллекции параметров. Использование в объекте Recordset одного значения или одной строки считается наименее масштабируемым решением благодаря дополнительной нагрузке, необходимой для многократного создания и раздробления этого объекта. Исходя из этого, в ADO всегда отдавалось предпочтение использованию коллекции параметров: paramscrapWOCount = _

cmdScrapWOByProduct. CreateParameter ( " ScrapWOCount11, _

DataTypeEnum.adlnteger, _

ParameterDirectionEnum.adParamOutput) cmdScrapWOByProduct.Parameters.Append(paramscrapWOCount) cmdScrapWOByProduct.Parameters.Item("ProductName").Value = sProduct- Name

В ADO.NET выбор вариантов гораздо шире, и выбор самого подходящего из них не столь очевиден. Значение может быть возвращено в объект DataTable, имеющий одну строку в длину. Этот метод имеет определенные преимущества в некоторых сценариях, где точка данных используется совместно с другими таблицами DataTable в объекте DataSet. К тому же может быть использован метод ExecuteNonQuery для заполнения переменных с помощью коллекции параметров, когда интерес вызывают несколько столбцов одной строки. Также может быть использован метод ExecuteScalar, когда необходимо получение только одного значения:

Dim iScrapWOCount As Integer = _ cmdScrapCount.ExecuteScalar()

или

cmdScrapCountByProduct.Parameters.Add("@ScrapWOCount", _

SqlDbType.Int).Direction = _

ParameterDirection.Output cmdScrapCountByProduct.ExecuteNonQuery()

Модификация данных

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

Пессимистическая модель конкуренции может оказаться полезной при массовой На заметку загрузке данных или в случае использования в инструкции ExecuteNonQuery запросов DML (insert, update или delete). Использование оптимистической модели конкуренции выгодно в тех случаях, когда приложению нужно при сбоях операций модификации данных предпринимать повторную попытку выполнения операции или записывать сообщение в журнал ошибок.

Обновление набора данных в приложении .NET требует не более чем обычной операции присвоения. Все или несколько строк в объекте DataSet могут быть вставлены, удалены или обновлены. Когда некоторая строка модифицируется в объекте DataSet, она помечается как измененная. Запуск метода Update объекта DataAdapter вызывает выполнение инструкции INSERT, UPDATE или DELETE, определенной в объекте, в базе данных с использованием адаптера данных. Существует вероятность, что между операциями чтения в адаптер данных и записью обновлений из него в базу некоторый другой пользователь уже изменил исходные данные в базе. В таком случае, если операция вставки срывается, в программном коде следует определить, имела ли место ошибка конкуренции. Это обычно выполняется с использованием столбца timestamp или с помощью сравнения исходных значений набора данных с текущими значениями базы данных в ходе выполнения метода Update. Разрешение возникающих коллизий конкуренции целиком возлагается на разработчика.

В ADO.NET 1.1 инструкции INSERT, UPDATE и DELETE, выполняемые методом Update, могут быть автоматически сгенерированы мастером конфигурирования адаптера таблицы. Сгенерированные инструкции сравнивают все столбцы таблицы в наборе данных с соответствующими столбцами базы данных, используя параметр конкуренции .NET CompareAllSearchableValues. Сгенерированные инструкции были неуправляемыми, малопроизводительными и не позволяющими удобно разрешать коллизии. В данной ситуации лучше использовать хранимые процедуры, даже для инструкций объекта DataAdapter. В ADO.NET 2.0 хранимые процедуры могут создаваться с помощью соответствующего мастера, хотя их сложно назвать оптимальными. Могут быть также определены различные параметры конкуренции, отличные от CompareAllSearchableValues. В частности, для идентификации возникновения коллизии можно использовать параметр CompareRowVersion для проверки изменения первичного ключа и версии строки, а также OverwriteChanges для проверки только первичного ключа. Эти параметры несколько улучшают работу метода обновления, однако все же лучше создавать собственные инструкции для адаптера данных, используя при этом хранимые процедуры, а не внедренные в объект инструкции SQL.

Связывание с элементами управления

Чтобы сократить объем создаваемого вручную программного кода, в Visual Studio для связывания данных с элементом управления требуется всего лишь перетащить компонент данных на нужный элемент. В результате будет создан связанный элемент управления данными. Ясно, что потребуются и дополнительные действия, однако это уже относится не к программированию в ADO.NET, а к вопросам проектирования форм.

Резюме

В этой главе мы сравнили объектные модели ADO и ADO.NET и исследовали некоторые их преимущества. По всеобщему признанию, предпочтение отдается ADO.NET. Несмотря на то что в некоторых сценариях использование ADO.NET 1 jc вряд ли имеет превосходство над использованием старой доброй ADO, в этой главе мы попытались показать, что версия ADO.NET 2.0 предложила на настоящий момент наиболее полноценную технологию высокоуровневого доступа к данным, разработанную компанией Microsoft.

Источник: Нильсен, Пол. Microsoft SQL Server 2005. Библия пользователя. : Пер. с англ. — М. : ООО “И.Д. Вильямс”, 2008. — 1232 с. : ил. — Парал. тит. англ.

По теме:

  • Комментарии