Существует много приложений, особенно Web- и n-уровневых, использующих ADO как средство взаимодействия с системами управления базами данных. ADO создавался для того, чтобы можно было обращаться к данным из приложения напрямую или по двухуровневой схеме. Со временем разработчики Microsoft расширили объектную модель ADO, в ответ на просьбы пользователей обеспечить поддержку работы приложений при отсутствии постоянной связи клиентского приложения и сервера, возможность разработки n-уровневой архитектуры программного обеспечения и интеграции с XML. Microsoft Framework .NET предлагает совсем новую объектную модель, заставляя разработчиков задуматься: портировать или не портировать? Менять свои приложения по частям или переписать все сразу? Хранить ли верность ADO или переходить на ADO.NET?

Архитектура .NET Framework привнесла в схему доступа к данным новый уровень, который обеспечивают две главные группы классов — базовые классы ADO.NET и XML.

В ADO.NET можно найти классы DataSet и DataReader, которые представляют независимые от базы данных контейнеры данных. Здесь есть инструменты, ориентированные на базу данных, такие, как команды SQL и OLE DB, управляемые провайдеры данных и соединения, считыватели данных и адаптеры данных. ADO.NET предоставляет компонент .NET для работы с данными вне зависимости от источника данных, формата данных или их физического расположения. Этот компонент привносит новую объектную модель и, что важнее, новые концепции DataSet и DataReader. Он характеризуется подходом, ориентированным на данные и отличным от подхода ADO, ориентированного на базы данных, что, естественно, ближе к современным требованиям программирования для Web.

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

Для того чтобы использовать объекты ADO в приложениях .NET, нужно познакомиться с некоторыми инструментами и методами. В реальных приложениях применять ADO в .NET не рекомендуется, его следует использовать как промежуточный шаг на пути к полному портированию приложений на ADO.NET. Сначала я расскажу об этих инструментах, а затем продемонстрирую мощную технологию импортирования, с применением объекта ADO RecordSet и объекта ADO.NET DataTable. Такой способ импорта идеален в том случае, когда для взаимодействия с приложениями используется COM-объект промежуточного уровня.

Применение ADO в ADO.NET

Несмотря на свою мощность, объектная модель ADO.NET не охватывает всей функциональности ADO. Например, в версии 1.0 ADO.NET отсутствуют поддержка серверных курсоров и расширение объектной модели ADO Extensions (ADOX), которое можно задействовать для программного управления схемами таблиц. Если обойти эти проблемы нельзя, но требуется перевести приложения на .NET, необходимо сохранить ADO и найти способ использовать его в приложениях .NET.

Объекты ADO содержатся в библиотеке COM-объектов, которая называется msado15.dll и обычно располагается в каталоге C:program filescommon filessystemado. Цифра 15 в названии не означает, что версия это ADO 1.5 и что вы обнаружили не тот файл. Все последние версии ADO (от 2.1 до 2.7) используют файлы с этим именем.

Для использования ADO в приложениях, разработанных на .NET, нужно создать класс, описав его как .NET-совместимый, поскольку приложения .NET не могут вызывать COM-объекты вроде тех, которые расположены в библиотеке ADO. После установки .NET Framework у вас появится исполняемый файл adodb.dll, находящийся в каталоге C:program filesmicrosoft.net primary interop assemblies. Этот файл необходим для импорта кода ADO в любую модель приложений .NET — Windows Forms, Web Forms и Web Services. Если на машине все еще установлена бета-версия .NET, которая используется в целях тестирования, нужной версии файла adodb.dll там может не оказаться. Его можно пересобрать в любое время, используя утилиту tlbimp.exe из .NET Framework. Она запускается из командной строки:

tlbimp «C:Program FilesCommon FilesSystemadomsado15.dll»

Утилита tlbimp.exe хранится в подкаталоге Bin, там, куда была установлена среда .NET Framework. Обычно это следующий путь: C:program filesmicrosoft visual studio .netframeworksdkin. Файл adodb.dll содержит классы .NET, которые предлагают тот же программный интерфейс, что и библиотека ADO, основанная на COM-объектах. Приложения .NET обращаются к этим классам, которые в свою очередь связываются с объектами ADO.

Для Web-приложений необходимо убедиться, что копия файла adodb.dll содержится в подкаталоге Bin виртуального каталога приложения. Если приложение не имеет своего виртуального каталога, следует разместить adodb.dll в корневом каталоге Web-сервера (т. е. в C:inetpubwwwrootin). Сохранив файл в нужном месте, можно использовать объект ADODB.Recordset и другие объекты ADO в любых приложениях .NET. Чтобы понять, как использовать ADO в .NET, разберем тестовую страницу ASP.NET Web Forms.

Любая страница Web Forms есть не что иное, как текстовый файл с расширением .aspx. Для того чтобы написать такой файл, необязательно устанавливать Visual Studio .NET, с этим справится любой текстовый редактор.

В частности, я использовал редактор Notepad для редактирования и C# для написания кода в примерах приложения. Сначала необходимо слинковать исполняемый модуль adodb.dll добавлением директивы @ Assembly в начале файла

<%@ Assembly Name=»ADODB» %>

Чтобы вызвать любой объект в сборке, следует использовать префикс пространства имен ADODB. Тогда для создания нового набора данных нужно задействовать следующий синтаксис:

ADODB.Recordset adoRS = new ADODB.Recordset();

Тем не менее, если добавить специальную директиву Import

<%@ Import Namespace=»ADODB» %>

можно объявлять набор данных более компактно:

Recordset adoRS = new Recordset();

Листинг 1. Выбор и просмотр записей в Recordset.
С этого места можно писать программный код, используя ADO. Например, для выборки RecordSet и перебора полученных записей можно применить код из Листинга 1. Это часть кода приложения, которая формирует Recordset и создает набор кнопок выбора. На Экране 1 показан результат работы приложения. В Листинге 1 представлена основная часть текста кода — файл ImportAdo.aspx.

Листинг 2. Использование C# для публикации ADO Recordset в Web Form.

Из текста Листинга 2 видно, что происходит подсоединение к базе данных, используется объект ADO Recordset для получения нескольких строк, затем строится строка HTML, отображающая набор кнопок. Также заслуживает упоминания применение объекта StringBuilder. .NET рассматривает строки как замкнутый и неизменяемый объект. Хотя языки высокого уровня предлагают операторы как + и += для конкатенации строк, использование данных операторов — не самый эффективный способ объединения строк. Поскольку строки неизменяемые, при соединении двух строк программный код создает новую строку соответствующего размера и помещает содержимое этих двух строк в нее. Для построения увеличивающихся строк рекомендуется использовать объекты StringBuilder, особенно в сценариях Web-форм, потому что в таком случае строка каждый раз прибавляется к первой строке без создания объекта для новой строки.

Оставаться или переходить?

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

Первый, главный, фактор, который может повлиять на решение, — это обширный список языков, которые поддерживает платформа .NET. Три наиболее важных языка — C#, Visual Basic .NET и JScript .NET. C# — новый язык, реализованный только и VBScript, но содержит несколько новых свойств и много новых настроек по умолчанию, которые могут легко нарушить работу существующего кода. Из этих трех языков JScript .NET по набору возможностей наиболее близок своему предшественнику — JScript. Однако меньше всего кода под ADO написано на языке JScript.

Чаще всего код ADO пишется на VB, и он не полностью совместим с Visual Basic .NET. Помимо новых конструкций и нового видения есть много мелких отличий между VB и Visual Basic .NET. Во врезке «VB против Visual Basic .NET» основные отличия перечислены. В общем, использование ADO и Recordsets не гарантирует, что существующий программный код сохранится в .NET без изменений.

Второй фактор, который необходимо учитывать, — привязка к данным в .NET, т. е. возможность привязывания данных к управляющим элементам пользовательского интерфейса. Сохранение записей в устаревшем контейнере для данных, таком, как ADO Recordset, не позволяет воспользоваться преимуществами предусмотренных в .NET управляющих элементов в плане привязки к данным. Среди таких элементов DataGrid, DataList и DropDownList они реально могут изменить вид приложения, создавая более простой интерфейс и при этом увеличивая общую скорость разработки.

От набора данных Recordsets к DataTables

Листинг 3. Сценарий конвертации ADO Recordset в объект.
Далее я покажу, как преобразовать старые объекты ADO Recordset в объекты ADO.NET, которые проще интегрировать с приложениями .NET. Программный код, представленный в Листинге 1, использует в основном циклы While для просмотра объекта Recordset и генерации списка кнопок выбора. При создании приложения проще и компактнее, как показано в Листинге 3. Требуется подключить сборку System.Data.OleDb, чтобы использовать класс OleDbDataAdapter, который преобразует Recordset в объект ADO.NET.

Программный код, представленный в Листинге 3, преобразует Recordset в объект ADO.NET — DataTable, который можно связать с любым управляющим элементом, поддерживающим привязку к данным. Хотя функциональной идентичности нет, объект DataTable может рассматриваться как копия в ADO.NET неподсоединенного объекта Recordset. В ADO можно получить неподсоединенный объект Recordset, используя статический, на стороне клиента, курсор.

Для выполнения преобразования Recordset-to-DataTable используется метод Fill из объекта OleDbDataAdapter.

DataTable dt = new DataTable();

OleDbDataAdapter oda = new OleDbDataAdapter();

oda.Fill(dt, adoRS);

Метод Fill заполняет объект DataTable данными из выбранного объекта Recordset. Во время выполнения операции метод Fill создает необходимые столбцы и добавляет строки. Если присутствует информация о первичном ключе, метод Fill сопоставляет каждую новую строку с уже имеющимися строками. Если соответствие находится, этот метод заменяет существующую строку новой. Если соответствие не найдено или если информация о первичном ключе недоступна, метод Fill просто добавляет строку из Recordset к объекту DataTable.

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

Если необходимо только загрузить все результирующие наборы в один контейнер, предпочтительнее использовать объект DataSet вместо DataTable.

DataSet — просто коллекция объектов DataTable. Для того чтобы импортировать Recordset в объект DataSet, следует задействовать одну из функций перегрузки метода Fill. В приведенном ниже коде метод Fill использует в качестве аргумента объекты DataSet, Recordset и третий аргумент, который будет рассмотрен ниже:

OleDbDataAdapter da =

new OleDbDataAdapter();

DataSet ds = new DataSet();

da.Fill(ds, adoRS, «MyTable»);

В приведенном выше примере метод Fill автоматически закрывает Recordset. Все результирующие наборы из оригинального объекта Recordset присутствуют как отдельные таблицы внутри объекта DataSet. Тем не менее в этом случае имеется слабый контроль над тем, как называется каждый объект DataTable. Когда вызывается метод Fill — передачей объекта DataSet, — можно задать имя таблицы MyTable с помощью фрагмента кода, приведенного выше. Это будет имя первой созданной таблицы, т. е. первый результирующий набор из ADO Recordset. Следующие получаемые наборы данных будут именоваться автоматически так же, как и первый, при этом к имени будет прибавляться текущий номер: MyTable1, MyTable2 и т. д. После того как объект DataSet создан, можно переименовать дочерние таблицы:

ds.Tables[«MyTable1»].TableName = «NewNameOfTable1»;

ds.Tables[«MyTable2»].TableName = «NewNameOfTable2»;

Промежуточный уровень

Способность подсоединяться к элементам управления, поддерживающим привязку к данным, — важная характеристика модели программирования в ASP.NET. Многие элементы управления в структуре приложений Framework .NET — как в модели Web Forms, так и в модели Windows Forms — позволяют источнику данных использовать их графический интерфейс. Источники данных для таких элементов управления должны быть объектами «коллекция». Recordset в ADO представляет собой коллекцию, но не специально определенную для .NET. Поэтому необходимо конвертировать Recordset во что-то еще (например, в объект DataTable), чтобы связать с элементами управления, такими, как CheckBoxList или DropDownList. Приведенный пример иллюстрирует необходимость обращаться с ADO и объектами Recordset при работе с кодом в .NET крайне осторожно.

В приложениях Web Forms и Windows Forms Recordset может быть только промежуточным объектом, который кэширует данные от провайдера данных OLE DB, но не может сделать их доступными для специализированных элементов управления с привязкой к данным.

Класс OleDbDataAdapter метода Fill поможет обойти названные ограничения. Этот метод позволяет импортировать данные в новое приложение, созданное на .NET, таким образом, что существующие бизнес-приложения и приложения с доступом к данным смогут вернуть ADO Recordset. На практике вместо импортирования библиотек ADO в приложения .NET импортируются объекты промежуточного уровня. До тех пор пока эти бизнес-объекты будут возвращать ADO Recordset по запросу, можно легко конвертировать объекты Recordset в объекты ADO.NET, тем самым увеличивая результативность привязки данных.

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

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


VB против Visual Basic .NET

Несоответствия между Visual Basic (VB) и Visual Basic .NET заключаются в следующем:

  • Visual Basic .NET требует использования круглых скобок при вызове метода;
  • аргументы Visual Basic .NET по умолчанию установлены в ByVal при передаче подпрограммам и функциям;
  • в Visual Basic .NET Wend и Static уже не являются ключевыми словами;
  • типы данных более строгие и размер некоторых типов данных в Visual Basic отличается от аналогичных Visual Basic .NET. В качестве примера можно привести тип Integer, который увеличен до 32 разрядов, вместо 16;
  • в Visual Basic .NET управление исключениями разрешается через операторы Try/Catch вместо On Error/GoTo;
  • определяемые пользователем типы данных в VB заменены структурой, поэтому в Visual Basic .NET придется задействовать Structure/End Structure вместо Type/End Type.

Кроме того, два языка обращаются с классами по-разному. В Visual Basic .NET кодирование классов происходит в файлах с расширением .vb, а не .cls. Любой модуль класса может содержать более одного класса и декларируется с новым синтаксисом, Class/End Class, что больше похоже на VBScript, чем на VB 6.0.

Дино Эспозито работает в Риме преподавателем и консультантом. С ним можно связаться по электронной почте по адресу: dinoe@wintellect.com.