□ ADOQuery — запрос ADO, позволяет выполнять SQL-команды для получения информации из ADO-источника данных и позволяет другим компонентам управлять этими данными, связываясь с компонентом ADOTable через компонент DataSource;
□ ADOStoredProc — хранимая процедура ADO, позволяет приложениям получать доступ к хранимым процедурам, используя интерфейс ADO;
□ RDSConnection — RDS-соединение, служит для управления передачей объекта Recordset от одного процесса (компьютера) к другому. Компонент используется для создания серверных приложений.
Компонент ADOConnection может использоваться как посредник между данными и другими компонентами ADO, что позволяет более гибко управлять соединением.
Возможен вариант использования других компонентов ADO, соединяясь с источником данных напрямую, для чего компоненты ADO имеют свойство
286
Часть II. Технологии доступа к данным
Connectionstring, с помощью которого могут создавать свой собственный канал доступа к данным.
Установление соединения
При использовании компонентов доступа к данным по технологии ADO
(ADOCommand, ADODataSet, ADOTable, ADOQuery И ADOStoredProc) установление соединения с хранилищем данных можно выполнить двумя путями: с помощью свойства Connectionstring или с помощью компонента ADOConnection. Имя последнего задается в свойстве Connection компонентов доступа к данным. При этом во втором случае для компонента ADOConnection предварительно также с помощью его свойства Connectionstring нужно установить соединение с хранилищем данных.
Рассмотрим технологию установления соединения с хранилищем данных с помощью свойства Connectionstring. Это свойство представляет собой строку с параметрами соединения, отделяемыми друг от друга точкой с запятой. Предварительно соответствующий компонент доступа к данным (например, ADODataSet) или компонент соединения (ADOConnection) должен быть помещен на форму приложения. Настройка параметров соединения осуществляется в диалоге (рис. 10.2), открываемом двойным щелчком в строке Connectionstring свойства соответствующего компонента доступа к данным в окне Инспектора объектов.
Рис. 10.2. Первое окно настройки строки соединения
При установке переключателя Use Data Link File можно выбрать из списка или найти (после нажатия кнопки Browse) файл связи с данными. udl. По умолчанию он расположен в папке c:\Program Files\Common Files\System\01e DB\Data Links. По существу файлы связи с данными играют ту же роль, что и псевдонимы при использовании BDE. Они позволяют разработчику не связывать откомпилированные приложения с точным расположением хранилища данных. При перемещении хранилища данных в другое место достаточно исправить содержимое файла связи с данными.
Глава 10. Технология ADO
287
При установке переключателя Use Connection String выполняются действия по созданию строки соединения. Рассмотрим их более подробно. Для продолжения выбранного варианта диалога нужно нажать кнопку Build. В результате открывается диалоговое окно Data Link Properties, содержащее 4 вкладки. С помощью вкладки Provider (рис. 10.3) осуществляется выбор провайдера с учетом характера решаемой задачи. По умолчанию предлагается вариант Microsoft OLE DB Provider for ODBC Drivers.
Рис. 10.3. Вкладка Provider окна настройки соединения
Отметим, что после установки Microsoft ActiveX Data Objects в операционной системе доступны стандартные провайдеры ADO, обеспечивающие следующее:
□ Microsoft Jet OLE DB Provider — соединение с данными СУБД Microsoft
Access;
□ Microsoft OLE DB Provider for Microsoft Indexing Service — доступ для чтения к ресурсам Microsoft Indexing Service;
□ Microsoft OLE DB Provider for Microsoft Active Directory Service — доступ к ресурсам службы каталогов Active Directory;
□ Microsoft OLE DB Provider for Internet Publishing — доступ к ресурсам Microsoft FrontPage и Microsoft Internet Information Server;
288
Часть II. Технологии доступа к данным
П Microsoft Data Shaping Service for OLE DB — доступ к иерархическим наборам данных;
□ Microsoft OLE DB Simple Provider — доступ к хранилищам данных, поддерживающим основные возможности OLE DB;
□ Microsoft OLE DB Provider for ODBC drivers — доступ к данным для драйверов ODBC;
□ Microsoft OLE DB Provider for Oracle — соединение с сервером Oracle;
□ Microsoft OLE DB Provider for SQL Server — соединение с сервером Microsoft SQL Server.
При нажатии на кнопку Next (см. рис. 10.3) происходит переход на вкладку Connection, содержимое которой несколько изменяется в зависимости от выбора провайдера. К примеру, вид вкладки Connection диалогового окна Data Link Properties для случая выбора провайдера Microsoft Jet 4.0 OLE DB Provider приведен на рис. 10.4.
Рис. 10.4. Вкладка Connection окна настройки соединения
На вкладке Connection можно указать имя базы данных, имя пользователя и пароль (для защищенных БД). Кроме того, нажав кнопку Test Connection, можно проверить правильность функционирования соединения. Далее можно нажатием
Глава 10. Технология ADO
289
кнопки OK установить строку соединения, либо перейти на остальные две вкладки.
На вкладке Advanced в поле Network Settings задается уровень защиты при сетевом доступе к базе данных. В поле Connect timeout задается предельное время ожидания соединения в секундах. В списке Access permissions для определения прав доступа задается перечень допустимых операций: Read — только чтение; ReadWrite — чтение и запись; Share Deny None — нет запрета на чтение и запись; Share Deny Read — запрещено открытие для чтения; Share Deny Write — запрещено открытие для записи; Share Exclusive — эксклюзивное (монопольное) использование; Write — только запись.
На вкладке All диалогового окна настройки можно просмотреть и отредактировать параметры соединения, заданные с помощью других вкладок.
В случае использования компонента ADOConnection для активизации соединения после настройки достаточно установить свойству connected этого компонента значение True или при выполнении приложения вызвать метод Open.
В случае использования любого из компонентов доступа к данным (ADODataSet, ADOTable, ADOQuery и ADOStoredProc) для активизации соединения после настройки используют свойство Active.
Управление соединением и транзакциями
Как следует из изложенного, установление соединения с хранилищем данных может осуществляться компонентами доступа к данным ADO через их свойство
ConnectionString.
Кроме того, компоненты доступа к данным ADO могут соединяться с хранилищем данных через свойство connection, связывающее их с компонентом соединения ADOConnection. При этом последний компонент связывается с хранилищем данных через СВОе СВОЙСТВО ConnectionString.
Достоинство применения компонента ADOConnection для связи компонентов доступа к данным с хранилищами данных состоит в том, что он позволяет управлять параметрами соединения и транзакциями.
С ПОМОЩЬЮ СВОЙСТВа CoursorLocation ТИПа TCursorLocation МОЖНО задать библиотеку, используемую курсором при соединении с хранилищем данных. Используемое по умолчанию значение ciuseciient означает, что все данные располагаются и обрабатываются на компьютере-клиенте. При этом достигается наибольшая гибкость: возможны операции, которые могут не поддерживаться сервером. Тем не менее операторы SQL все равно выполняются на сервере, а клиенту передаются результаты выполнения запроса.
Если свойству CoursorLocation задано значение ciuseServer, то обработка данных ведется на сервере. Такое значение свойства целесообразно устанавливать в случае задания команд, возвращающих большой объем данных.
290
Часть II. Технологии доступа к данным
При использовании технологии ADO соединение может быть синхронным или асинхронным, что можно задать с помощью свойства Connectoptions типа
TConnectoption, который описан так:
type TConnectOption = (coConnectUnspecified, coAsyncConnect);
Значение coConnectUnspecified задает синхронное соединение, которое всегда ожидает результат последнего запроса, значение coAsyncConnect задает асинхронное соединение, при котором новые запросы выполняются, не ожидая ответа от предыдущих запросов.
Перед установлением соединения возникает событие onwiiiconnect типа
TwiiiconnectEvent, который описан так:
TWillConnectEvent = procedure(Connection: TADOConnection; var ConnectionString, UserlD, Password: WideString; var ConnectOptions: TConnectOption; var EventStatus: TEventStatus) of object;
Здесь: connection указывает на соответствующий компонент соединения; ConnectionString, Password, WideString определяют строку соединения, ИМЯ и пароль пользователя соответственно; Connectoptions указывает на синхронное или асинхронное соединение.
Параметр EventStatus указывает на успешность выполнения запроса на соединение. Тип этого параметра описан так:
type TEventStatus =
(esOK,esErrorsOccured,esCantDeny,esCancel,esUnwantedEvent);
Здесь, например: esOK — соединение выполнено успешно; esErrorsOccured — ошибка при выполнении операции; esCantDeny — незаконченную операцию соединения нельзя отменить.
После установки соединения возникает событие Onconnectcompiete типа
TConnectErrorEvent, который описан так:
TConnectErrorEvent = procedure(Connection: TADOConnection; Error: Error; var EventStatus: TEventStatus) of object;
В случае возникновения ошибки в процессе соединения параметр EventStatus будет иметь значение esErrorsOccured, а параметр Error будет содержать объект ошибки ADO.
(_____ ЗамечаниеJ
Объекты ошибки ADO содержат информацию об ошибке, возникшей при выполнении операции над каким-либо объектом ADO. Разработчик может использовать методы объекта ошибки интерфейса Error, предоставляемого многими методами других объектов ADO. Укажем важные свойства объекта ошибки. Свойство Description возвращает описание ошибки, переданное из объекта. Свойство SQLState содержит текст команды, вызвавшей ошибку. Свойство NativeError возвращает код ошибки, переданный из объекта, в котором ошибка произошла.
Глава 10. Технология ADO
291
Iри разрыве соединения возникает событие OnDisconnect ТИПа TDisconnectEvent,
который описан так:
TDisconnectEvent = procedure(Connection: TADOConnection; var EventStatus: TEventStatus) of object;
Управление транзакциями осуществляется с помощью методов и свойств компонента ADOConnection.
Для запуска транзакции используется функция BeginTrans, возвращающая целое значение — уровень вложенности новой транзакции. В случае успешного запуска транзакции свойство inTransaction принимает значение True, указывающее на то, что компонент соединения находится в транзакции.
Для завершения транзакции и сохранения внесенных изменений в хранилище данных используется метод commitTrans. При успешном его выполнении свойство inTransaction принимает значение False.
Для отката транзакции служит метод RoiibackTrans. При его успешном выполнении отменяются все изменения, внесенные в ходе транзакции, а свойство
inTransaction принимает значение True.
Для управления запуском транзакций, оставшихся незавершенными, служит свойство Attributes типа TXactAttributes. Оно принимает два значения: xaCommitRetaining — незавершенная транзакция начинается при подтверждении предыдущей транзакции; xaAbortRetaining — незавершенная транзакция начинается при отмене предыдущей транзакции.
Компоненты доступа к данным
Перечень и назначение компонентов работы по технологии ADO мы приводили в начале главы. Большинство из них имеет аналоги компонентов в технологиях BDE и dbExpress (табл. 10.1). В этой таблице компоненты, используемые в технологии dbExpress, аналогами можно назвать достаточно условно, т. к. большинство из них поддерживают однонаправленные наборы данных.
Таблица 10.1. Соответствие компонентов в технологиях ADO, dbExpress и BDE
292
Часть II. Технологии доступа к данным
Стандартные компоненты доступа к данным в ADO наследуют механизм доступа от родительского класса TCustomADODataSet. Поэтому важнейшие свойства и методы этого класса во многом определяют поведение компонентов доступа к данным в ADO. Коротко охарактеризуем их.
К числу основных свойств названного класса можно отнести свойства, устанавливающие параметры обмена с хранилищем данных. Значения их нужно задать до открытия набора данных.
Tun блокировки записей в наборе данных определяет свойство LockType типа
TADOLockType, который описан так:
type TADOLockType = (ltUnspecified, ltReadOnly, ltPessimistic, ltOptimistic, ltBatchOptimistic);
Здесь, например:
□ ltUnspecified — блокировка задается источником данных;
□ ltReadOnly — набор данных открывается в режиме только для чтения;
□ ltPessimistic — блокировка на время редактирования до момента подтверждения.
Как отмечалось, местоположение курсора задает свойство CursorLocation (см. предыдущий подраздел). При работе с клиентским курсором важную роль играет следующее свойство.
Передаваемые серверу данные определяет свойство Marshaioptions типа TMarshaioption, который описан так:
type TMarshalOption = (moMarshalAll, moMarshalModifiedOnly); Здесь:
□ moMarshalAll — возврат всех записей локального набора данных серверу;
□ moMarshalModif iedOnly — возврат только измененных записей.
Тип курсора определяет свойство CursorType типа TCursorType, который описан так:
type TCursorType = (ctUnspecified, ctOpenForwardOnly, ctKeyset,ctDynamic, ctStatic);
Здесь, например:
□ ctUnspecified — тип курсора не задан и определяется возможностями источника данных;
□ ctOpenForwardOnly — однонаправленный курсор, используемый для одиночного прохода по всем записям;
□ ctKeyset — двунаправленный курсор, не отображающий добавленные или удаленные другими пользователями записи;
□ ctstatic — двунаправленный курсор, не учитывающий изменения записей другими пользователями.
Глава 10. Технология ADO
293
Набор данных может быть открыт с помощью свойства Active или метода Open. На стороне клиента записи из набора данных хранятся в буфере, размер которого может быть получен с помощью свойства cacheSize типа integer.
При необходимости с помощью свойства BiockReadSize типа integer можно организовать передачу записей в виде блоков. Кроме того, с помощью свойства MaxRecords типа integer можно ограничить размер набора данных. По умолчанию блочная пересылка не используется, а число записей в наборе данных не ограничено.
Текущее состояние записи набора данных определяет свойство Recordstatus типа TrecordstatusSet, который описан так:
type TRecordStatus = (rsOK, rsNew, rsModified, rsDeleted, rsUnmodified, rslnvalid, rsMultipleChanges, rsPendingChanges, rsCanceled, rsCantRelease, rsConcurrencyViolation, rsIntegrityViolation, rsMaxChangesExceeded, rsObjectOpen, rsOutOfMemory, rsPermissionDenied, rsSchemaViolation, rsDBDeleted);
Здесь, например:
□ rsOK — запись успешно изменена;
□ rsNew — новая запись вставлена;
□ rsModified — запись изменена;
□ rsDeleted — запись удалена;
□ rsUnmodified — запись осталась без изменений.
Дадим сравнительно развернутую характеристику компонентам, используемым в технологии ADO для доступа к данным.
Доступ к таблицам
Для обеспечения доступа к таблицам хранилищ данных по технологии ADO служит компонент ADOTable. Для установления соединения с хранилищем данных этого компонента через провайдеры ADO служит свойство Connectionstring или Connection, как описано ранее. Для управления набором данных таблицы в приложение включают компонент источника данных DataSource. При этом свойству DataSet этого компонента в качестве значения задается имя компонента ADOTable. Для отображения данных таблицы к источнику данных подключаются различные компоненты отображения, к примеру, dbgrid.
После установления связи компонента ADOTable с хранилищем данных с помощью свойства TableName типа wideString задается имя таблицы. Не все провайдеры ADO допускают непосредственный доступ к таблицам, поэтому может потребоваться доступ с помощью SQL-запроса. Вариант доступа к данным таблицы определяет свойство TableDirect типа Boolean. Если оно имеет значение False (по умолчанию), то компонент ADOTable автоматически генерирует SQL-запрос для доступа к таблице, в противном случае выполняется непосредственный доступ к данным таблицы.
294
Часть II. Технологии доступа к данным
Рассматриваемый нами компонент по своим возможностям и технике работы с ним во многом схож с компонентом Table. Здесь также с помощью редактора полей можно задавать свойства отдельных полей. При этом имеется ограничение, состоящее в том, что в компонентах ADO нельзя работать со словарями. Поэтому свойства полей требуется задавать вручную. Кроме того, у драйверов ADO имеются ограничения по работе с отдельными типами полей, в частности, с графическими.
Программирование действий по работе с хранилищем данных с помощью рассматриваемого компонента используются аналогичные средства, как и в случае компонента Table. В частности, для навигации по табличному набору данных используются методы First, Last, Next и Prior. Для поиска записей используются методы Find, Seek и Locate.
Выполнение запросов
Для выполнения SQL-запросов при использовании технологии ADO служит компонент ADOQuery. По функциональным возможностям и технике применения этот компонент во многом подобен компоненту Query. Установка соединения с хранилищем данных, свойства и методы фильтрации и поиска аналогичны используемым для компонента ADOTable.
Текст запроса задается с помощью свойства sql типа TStrings.
С помощью свойства Parameters типа TParameters определяются параметры запроса.
Открытие набора данных может быть выполнено с помощью свойства Active типа Boolean или с помощью метода Open. Если же запрос не должен возвращать данных, то для открытия набора данных можно вызвать метод ExecSQL.
Вызов хранимых процедур
Для вызова хранимых процедур по технологии ADO служит компонент ados-toredProc. По своим возможностям и технике использования он подобен своему аналогу из BDE. Установка соединения с хранилищем данных и управление набором данных аналогичны используемым для компонента ADOTable. Для отображения данных (выходных параметров) к источнику данных также подключаются компоненты отображения.
Для задания имени хранимой процедуры служит свойство ProcedureName типа WideString.
Свойство Parameters типа TParameters служит для определения входных параметров процедуры. А именно, после задания имени хранимой процедуры в свойстве Parameters отображаются входные параметры процедуры. Их можно просмотреть с помощью Инспектора объектов.
Выходные параметры хранимой процедуры являются объектами полей рассматриваемого компонента ADOStoredProc. Чтобы просмотреть и изменить их значения, достаточно с помощью контекстного меню компонента ADOStoredProc
Глава 10. Технология ADO
295
вызвать редактор полей Fields Editor. С помощью команд редактора можно легко изменить состав полей (выходные параметры), отображаемых в наборе данных компонента ADOStoredProc.
Компонент ADODataSet
Компонент ADODataSet служит для представления набора данных из хранилища данных ADO. По своим функциональным возможностям компонент в определенной мере аналогичен компонентам SQLDataSet и SQLSimpleDataSet, используемым в технологии dbExpress. Этот компонент позволяет получать данные из таблиц, SQL-запросов, хранимых процедур, файлов и т. д.
Тип команды, указываемой В СВОЙСТВе CommandText, определяет СВОЙСТВО CommandType
типа TCommandType, который определен так:
TCommandType = (cmdUnknown, cmdText, cmdTable, cmdStoredProc, cmdFile, cmdTableDirect)
Здесь:
□ cmdUnknown — тип не известен;
□ cmdText — текст SQL-оператора или вызова процедуры (значение по умолчанию);
□ cmdTable — ИМЯ таблицы;
□ cmdStoredProc — имя хранимой процедуры;
□ cmdFile — имя сохраненного файла набора данных;
□ cmdTableDirect — имя таблицы, все поля которой возвращаются.
Значение свойства CommandText типа widestring определяет команду, которая выполняется. В качестве команды может быть задана строка с SQL-оператором, имя таблицы или имя хранимой процедуры. При необходимости могут быть заданы параметры с помощью свойства Parametrs. Выполнение команды, заданной с помощью свойства CommandText, происходит при открытии набора данных.
Установка соединения с хранилищем данных и управление набором данных аналогичны используемым для компонента ADOTable. Для отображения данных к источнику данных (компоненту DataSource) также подключаются компоненты отображения.
Команды ADO
Для выполнения команд предназначен компонент ADOCommand, являющийся реализацией объекта ADO command в среде Delphi. Этот компонент служит для выполнения команд, не возвращающих результаты, например, SQL-операторов языка определения данных или хранимых процедур. Для выполнения хранимых процедур и SQL-запросов, возвращающих результаты в виде наборов данных,
Целесообразно ПрИМеНЯТЬ КОМПОНеНТЫДОСТупа К ДаННЫМ ADODataSet, ADOQuery
И ADOStoredProc.
296
Часть II. Технологии доступа к данным
Рассмотрим важнейшие свойства и методы компонента ADOCommand. Отметим, что большинство свойств компонента ADOCommand в Delphi эквивалентны свойствам объекта ADO Command.
Свойство commandobject типа _command предоставляет непосредственный доступ к базовому объекту команды ADO command.
Тип команды, указываемой в свойстве commandText, определяет свойство CommandType (см. описание компонента ADODataSet). Для свойства CommandType объекта ADOCommand значения cmdFile И cmdTableDirect ЯВЛЯЮТСЯ недопустимыми.
Напомним, что значение свойства CommandText типа widestring определяет команду, которая выполняется с помощью метода Execute. В качестве команды может быть задана строка с SQL-оператором, имя таблицы или имя хранимой процедуры. При необходимости могут быть заданы параметры с помощью свойства Parametrs.
Текущее состояние компонента ADOCommand (объекта command) определяет свойство states типа objectstates, который описан так:
TObjectState = (stClosed, stOpen, stConnecting, stExecuting, stFetching); Здесь:
□ stciosed — объект command не активен и не соединен с хранилищем данных;
□ stOpen — объект command не активен, соединен с хранилищем данных;
□ stConnecting — объект command соединяется с хранилищем данных;
□ stExecuting — объект Command ВЫПОЛНЯеТ Команду;
□ stFetching — объект Command получает данные от хранилища данных.
Условия выполнения команды ADO определяет свойство ExecuteOptions типа
TExecuteOptions, который описан так:
TExecuteOption = (eoAsyncExecute, eoAsyncFetch, eoAsyncFetchNonBlocking, eoExecuteNoRecords);
Здесь:
□ eoAsyncExecute — асинхронное выполнение команды;
□ eoAsyncFetch — асинхронная передача данных;
□ eoAsyncFetchNonBlocking — асинхронная передача данных без блокирования потока;
□ eoExecuteNoRecords — выполнение команды ADO без возвращения данных.
Выполнение команды ADO осуществляется с помощью одной из трех перегружаемых версий метода Execute с различными наборами параметров:
□ function Execute: _Recordset; overload; — такое объявление метода ис
пользуется при выполнении команды без параметров;
Глава 10. Технология ADO
297
function Execute(const Parameters: OleVariant): _Recordset; overload; — в этом объявлении параметр Parameters определяет параметры команды;
function Execute(var RecordsAffected: Integer; const Parameters: OleVariant): _RecordSet; overload; — здесь параметр RecordsAffected возвращает общее число обработанных запросом записей.
Пример приложения
Рассмотрим пример (рис. 10.5) приложения для работы с БД, использующего технологию ADO. Пусть назначением приложения является организация доступа к различным таблицам из базы данных, их редактирование и сохранение внесенных изменений на сервере.
Основными компонентами приложения, используемыми для установления соединения с базой данных и отображения данных, являются следующие:
ADOConnectionl, ADODataSetl, DataSourcel И DBGridl. Кроме ТОГО, имеется ряд вспомогательных компонентов, служащих для управления работой приложения.
Соединение с хранилищем данных компонента ADODataSetl выполнено через его свойство connection, указывающее на имя ADOConnectionl компонента соединения. Для компонента ADOConnectionl с помощью его свойства Connectionstring установлено соединение с хранилищем данных. При этом использован файл связи с данными. Для наглядности в процедуре обработки события создания формы приведен оператор задания нужного значения свойству Connectionstring компонента ADOConnectionl.
298
Часть II. Технологии доступа к данным
Для компонента DataSourcel его свойству DataSet установлено значение ADODataSetl. Для компонента DBGridl, используемого для отображения набора данных, его свойству DataSource установлено значение DataSourcel.
Код модуля формы для решения поставленной задачи имеет вид:
unit ADODataSet;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, DB, ADODB, Grids, DBGrids, ExtCtrls;
type
TForml = class(TForm)
ADODataSetl: TADODataSet;
DataSourcel: TDataSource;
DBGridl: TDBGrid;
ADOConnectionl: TADOConnection;
Panel1: TPanel;
UpdateButton: TButton;
GetTableButton: TButton;
Buttonl: TButton;
Editl: TEdit;
procedure FormlCreate(Sender: TObject);
procedure FormlCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure UpdateButtonClick(Sender: TObject);
procedure GetTableButtonClick(Sender: TObject);
procedure ButtonlClick(Sender: TObject);
private public
procedure UpdateData; end;
var
Forml: TForml;
implementation
{$R *.dfm}
Глава 10. Технология ADO
299
const
BaseFileName = 'EMPLOYEE.ADTG';
procedure TForml.UpdateData; begin