Использование ADO средствами Delphi


Наряду с традиционными инструментами доступа к данным Borland Database Engine и ODBC в приложениях Delphi можно применять технологию Microsoft ActiveX Data Objects (ADO), которая основана на возможностях СОМ, а именно интерфейсов OLE DB.
Технология ADO завоевала популярность у разработчиков, благодаря универсальности — базовый' набор интерфейсов OLE DB имеется в каждой современной операционной системе Microsoft. Поэтому для обеспечения доступа приложения к данным достаточно лишь правильно указать провайдер соединения ADO и затем переносить программу на любой компьютер, где имеется требуемая база данных и, конечно, установленная ADO.
В Палитре компонентов Delphi есть страница ADO, содержащая набор компонентов, позволяющих создавать полноценные приложения БД, обращающиеся к данным через ADO.
В этой главе рассматриваются следующие вопросы:

  •  краткий обзор технологии ADO, доступных провайдеров ADO, а также работающих в ней объектов и интерфейсов;
  •  как создать соединение с базой данных через ADO в приложении Delphi;
  •  применение объекта набора записей ADO в приложении;
  •  как использовать таблицы, запросы SQL и хранимые процедуры;
  •  что такое команды и объекты команды ADO.

 

Основы ADO


Технология Microsoft ActiveX Data Objects обеспечивает универсальный доступ к источникам данных из приложений БД. Такую возможность предоставляют функции набора интерфейсов, созданные на основе общей модели объектов СОМ и описанные в спецификации OLE DB.
Технология ADO и интерфейсы OLE DB обеспечивают для приложений единый способ доступа к источникам данных различных типов (1). Например, приложение, использующее ADO, может применять одинаково сложные операции и к данным, хранящимся на корпоративном сервере SQL, и к электронным таблицам, и локальным СУБД. Запрос SQL, направленный любому источнику данных через ADO, будет выполнен.
Возникает вопрос: каким образом источники данных смогут выполнить этот запрос?
За серверы БД беспокоиться не стоит, обработка запросов SQL — это их основная обязанность. Но как быть с файловыми последовательностями, электронными таблицами, файлами электронной почты и т. д.? Здесь на помощь приходят механизмы ADO и интерфейсы OLE DB.
OLE DB представляет собой набор специализированных объектов СОМ, инкапсулирующих стандартные функции обработки данных, и специализированные функции конкретных источников данных и интерфейсов, обеспечивающих передачу данных между объектами.
Согласно терминологии ADO, любой источник данных (база данных, электронная таблица, файл) называется хранилищем данных, с которым при помощи провайдера данных взаимодействует приложение. Минимальный набор компонентов приложения может включать объект соединения, объект набора данных, объект процессора запросов.
Примечание 
Объекты OLE DB создаются и функционируют так же, как и другие объекты СОМ. Каждому объекту соответствует идентификатор класса CLSID, хранящийся в системном реестре. Для создания объекта используется метод CoCreateinstance и соответствующая фабрика класса. Объекту соответствует набор интерфейсов, к методам которых можно обращаться после создания объекта.
В результате приложение обращается не прямо к источнику данных, а к объекту OLE DB, который "умеет" представить данные (например, из файла электронной почты) в виде таблицы БД или результата выполнения запроса SQL.
Технология ADO в целом включает в себя не только сами объекты OLE DB, но и механизмы, обеспечивающие взаимодействие объектов с данными и приложениями. На этом уровне важнейшую роль играют провайдеры ADO, координирующие работу приложений с хранилищами данных различных типов.
Такая архитектура позволяет сделать набор объектов и интерфейсов открытым и расширяемым. Набор объектов и соответствующий провайдер может быть создан для любого хранилища данных без внесения изменений в исходную структуру ADO. При этом существенно расширяется само понятие данных — ведь можно разработать набор объектов и интерфейсов и для нетрадиционных табличных данных. Например, это могут быть графические данные геоинформационных систем, древовидные структуры из системных реестров, данные CASE-инструментов и т. д.
Так как технология ADO основана на стандартных интерфейсах СОМ, которые являются системным механизмом Windows, это сокращает общий объем работающего программного кода и позволяет распространять приложения БД без вспомогательных программ и библиотек.
Примечание 
Нижеследующее описание спецификации OLE DB представлено в соответствии с официальной терминологией Microsoft для данной предметной области.
Спецификация OLE DB различает следующие типы объектов, которые будут рассмотрены ниже.

  •  Перечислитель (Enumerator) выполняет поиск источников данных или других перечислителей. Используется для обеспечения функционирования провайдеров ADO.
  •  Объект-источник данных (Data Source Object) представляет хранилище данных.
  •  Сессия (Session) объединяет совокупность объектов, обращающихся к одному хранилищу данных.
  •  Транзакция (Trasaction) инкапсулирует механизм выполнения транзакции.
  •  Команда (Command) содержит текст команды и обеспечивает ее выполнение. Командой может быть запрос SQL, обращение к таблице БД и т. д.
  •  Набор рядов (Rowset) представляет собой совокупность строк данных, являющихся результатом выполнения команды ADO.
  •  Объект-ошибка (Error) содержит информацию об исключительной ситуации.

Рассмотрим функциональные возможности основных объектов и интерфейсов OLE DB.
Перечислители
Объекты- перечислители обеспечивают поиск любых объектов ADO, которые имеют доступ к источникам данных. При этом другие перечислители также видны в данном перечислителе.
Первичный поиск источников данных осуществляется в провайдере ADO. Перечислители могут отбирать только источники данных конкретных типов, поэтому провайдер обеспечивает доступ к конкретному типу хранилища данных.
В составе ADO имеется системный корневой перечислитель, который выполняет начальный поиск других перечислителей и источников данных. Его можно использовать, зная его идентификатор класса CLSID_OLEDB_ENUMERATOR.
 Примечание 
В Delphi GUID глобального перечислителя содержится в файле \Delphi7\Source \Vcl\OleDB.pas.
CLSID_OLEDB_ENrjMERATOR: TGUID= '{C8B522DO-5CF3-11CE-ADE5-OOAA0044773D}
Функции перечислителя содержатся в интерфейсе isourcesRowset. Метод
function GetSourcesRowset(const punkOuter: lUnknown; const riid: TGUID; cPropertySets: UINT; rgProperties: PDBPropSetArray; out ppSourcesRowset: lUnknown): HResult; stdcall;
возвращает ссылку на объект набора рядов (см. выше), содержащий сведения о найденных источниках данных или перечислителях.
Объекты соединения с источниками данных
Внутренний механизм ADO, обеспечивающий соединение с хранилищем данных, использует два типа объектов. Это объекты-источники данных и объекты-сессии.
Объект-источник данных обеспечивает представление информации о требуемом реальном источнике данных и подключение к нему.
Для ввода сведений о хранилище данных используется интерфейс iDBProperties. Для успешного подключения необходимо задать обязательные сведения. Вероятно, для любого хранилища данных будет актуальной информация об его имени, пользователе и пароле. Однако каждый тип хранилища имеет собственные уникальные настройки. Для получения списка всех обязательных параметров соединения с данным хранилищем можно воспользоваться методом
function GetPropertylnfo(cPropertylDSets: UINT; rgPropertylDSets: PDBPropIDSetArray; var pcPropertylnfoSets: UINT; out prgPropertylnfoSets: PDBPropInfoSet; ppDescBuffer: PPOleStr): HResult; stdcall;
который возвращает заполненную структуру DBPROPINFO.
PDBPropInfo = ^TDBPropInfo;
 DBPROPINFO = packed record
pwszDescription: PWideChar;
dwPropertylD: DBPROPID;
dwFlags: DBPROPFLAGS;
vtType: Word;
vValues: OleVariant;
end; 
TDBPropInfo = DBPROPINFO;
Для каждого обязательного параметра в элементе dwFlags устанавливается значение DBPROPFLAGS_REQUIRED.
Для инициализации соединения необходимо использовать метод
function Initialize: HResult; stdcall;
интерфейса iDBinitiaiize объекта-источника данных.
Сессия
Из объекта-источника данных можно создавать объекты-сессии. Для этого используется метод
function CreateSession(const punkOuter: lUnknown; const riid: TGUID; out ppDBSession: lUnknown}: HResult; stdcall;
интерфейса iDBCreateSession. Сессия предназначена для обеспечения работы транзакций и наборов рядов.
Транзакции
Управление транзакциями в OLE DB реализовано на двух уровнях. Во-первых, всеми необходимыми методами обладает объект сессии. Он имеет интерфейсы ITransaction, ITransactionJoin, ITransactionLocal, ITransactionObject.
Внутри сессии транзакция управляется интерфейсами ITransactionLocal, ItransactionSC, ITransaction и их методами StartTransaction, Commit, Rollback.
Во-вторых, для объекта сессии можно создать объект транзакции при помощи метода
function GetTransactionObject(ulTransactionLevel: UINT; out ppTransactionObject: ITransaction): HResult; stdcall;
интерфейса ITransactionObject, который возвращает ссылку на интерфейс объекта-транзакции.
Наборы рядов
Объект-набор рядов является основным объектом ADO, обеспечивающим работу с данными. Он инкапсулирует совокупность рядов из источника данных, механизмы навигации по рядам и поддержания рядов в актуальном состоянии.
Объект сессии имеет обязательный интерфейс IOpenRowset с методом
function OpenRowset(const punkOuter: lUnknown; pTablelD: PDBID; plndexID: PDBID; const riid: TGUID; cPropertySets: UINT; rgPropertySets: PDBPropSetArray; ppRowset: PlUnknown): HResult; stdcall;
который открывает необходимый набор рядов.
В зависимости от возможностей источника данных набор рядов может поддерживать различные интерфейсы. Но пять из них являются обязательными:

  • IRowset — обеспечивает навигацию по рядам;
  • IAccessor — обеспечивает представление информации о формате рядов, содержащихся в буфере набора рядов;
  • IRowsetinfo — позволяет получить информацию о наборах рядов (например, число рядов или число обновленных рядов);
  • Icoiumnsinfo — позволяет получить информацию о колонках рядов (наименование, тип данных, возможность обновления и т. д.);
  •  IconvertType — содержит единственный метод canConvert, позволяющий определить возможность преобразования типов данных в наборе рядов.

Примечание
В отличие от привычной практики разработки интерфейсов в рамках модели СОМ, интерфейсы OLE DB часто имеют всего один-два метода. В результате большая группа интерфейсов реализует несколько вполне стандартных функций.
Дополнительные возможности по управлению набором рядов предоставляют следующие интерфейсы:

  •  IRowsetchange — выполняет изменения в наборе рядов (вносит изменения, добавляет новые ряды, удаляет ряды и т. д.);
  •  IRowsetidentity — позволяет сравнивать ряды разных рядов;
  •  IRowsetindex — обеспечивает использование индексов;
  •  IRowsetLocate — выполняет поиск в наборе рядов;
  •  IRowsetupdate — реализует механизм кэширования изменений.

Команды


Программные средства ADO были бы неполными, если бы не имели возможности использовать для работы с данными язык SQL. Операторы DML и DDL, ряд специальных операторов ADO носят общее название текстовых команд.
Объект-команда инкапсулирует саму текстовую команду и механизм обработки и передачи команды. Объект команды выполняет следующие операции:

  •  разбор текста команды;
  •  связывание команды с источником данных;
  •  оптимизацию команды;
  • передачу команды источнику данных.

Главный интерфейс объекта команды icommand имеет три метода:

  •  function Cancel: HResult; stdcall;

отменяет выполнение команды;

  •  function Execute(const punkOuter: lUnknown; const riid: TGUID; var pParams: DBPARAMS; pcRowsAffected: PInteger; ppRowset: PlUnknown): HResult; stdcall;

исполняет команду;

  •  function GetDBSession(const riid: TGUID; out ppSession: lUnknown): HResult; stdcall;

возвращает ссылку на интерфейс сессии, вызвавший данную команду.
Помимо основного, объект команды обеспечивает доступ к дополнительным интерфейсам:

  •  ICommandPrepare — содержит два метода (Prepare И Unprepare) для подготовки команды;
  •  icommandProperties — задает для команды свойства, которые должны поддерживаться возвращаемым командой набором данных;
  •  iCommandText — управляет текстом команды (этот интерфейс обязателен для объекта команды);
  •  icommandwithParameters — обеспечивает работу с параметрами команды.

 

Провайдеры ADO


Провайдеры ADO обеспечивают соединение приложения, использующего данные через ADO, с источником данных (сервером SQL, локальной СУБД, файловой системой и т. д.). Для каждого типа хранилища данных должен существовать провайдер ADO.
Провайдер "знает" о местоположении хранилища данных и его содержании, умеет обращаться к данным с запросами и интерпретировать возвращаемую служебную информацию и результаты запросов с целью их передачи приложению.
Список установленных в данной операционной системе провайдеров доступен для выбора при установке соединения через компонент TADOConnection.
При инсталляции Microsoft ActiveX Data Objects в операционной системе устанавливаются следующие стандартные провайдеры.

  •  Microsoft Jet OLE DB Provider обеспечивает соединение с данными СУБД Access при посредстве технологии ОАО.
  •  Microsoft OLE DB Provider for Microsoft Indexing Service обеспечивает доступ только для чтения к файлам и Internet-ресурсам Microsoft Indexing Service.
  •  Microsoft OLE DB Provider for Microsoft Active Directory Service обеспечивает доступ к ресурсам службы каталогов (Active Directory Service).
  •  Microsoft OLE DB Provider for Internet Publishing позволяет использовать ресурсы, предоставляемые Microsoft FrontPage, Microsoft Internet Information Server, HTTP-файлы.
  •  Microsoft Data Shaping Service for OLE DB позволяет использовать иерархические наборы данных.
  •  Microsoft OLE DB Simple Provider предназначен для организации доступа к источникам данных, поддерживающим только базисные возможности OLE DB.
  •  Microsoft OLE DB Provider for ODBC drivers обеспечивает доступ к данным, которые уже "прописаны" при помощи драйверов ODBC. Однако реальное использование столь экзотичных вариантов соединений представляется проблематичным. Драйверы ODBC и так славятся своей медлительностью, поэтому дополнительный слой сервисов здесь ни к чему.
  •  Microsoft OLE DB Provider for Oracle обеспечивает соединение с сервером Oracle.
  •  Microsoft OLE DB Provider for SQL Server обеспечивает соединение с сервером Microsoft SQL Server.

 

Реализация ADO в Delphi


Механизм доступа к данным через ADO и многочисленные объекты и интерфейсы реализованы в VCL Delphi в виде набора компонентов, расположенных на странице ADO. Все необходимые интерфейсы, обеспечивающие работу компонентов, объявлены и описаны в файлах OleDB.pas и ADODB.pas в папке \Delphi7\Source\Vcl.
Компоненты ADO
Компонент TADOConnection вобрал возможности перечислителя, источника данных и сессии с возможностями обслуживания транзакций.
Текстовые команды ADO реализованы в компоненте TADOCommand.
Наборы рядов (нотация Microsoft) можно получить при помощи компонентов TADOTable, TADOQuery, TAOostoredProc. Каждый из них реализует способ доступа к конкретному типу представления данных в хранилище. Далее по тексту, применительно к компонентам Delphi, совокупность возвращаемых из хранилища данных строк будем называть набором записей, что соответствует документации Inprise (см. www.borland.com или www.borland.ru) и стилю изложения предыдущих глав.
Набор свойств и методов компонентов ADO обеспечивает реализацию всех необходимых приложению БД функций. Способы использования компонентов ADO немногим отличаются от стандартных компонентов VCL доступа к данным (см. гл. 11).
Однако при необходимости разработчик может использовать все возможности интерфейсов ADO, обращаясь к ним через соответствующие объекты ADO. Ссылки на объекты имеются в компонентах (см. ниже).
Механизм соединения с хранилищем данных ADO
Компоненты доступа к данным ADO могут использовать два варианта подключения к хранилищу данных. Это стандартный метод ADO и стандартный метод Delphi.
В первом случае компоненты используют свойство connectionstring для прямого обращения к хранилищу данных. Во втором случае используется специальный компонент TADOConnection, который обеспечивает расширенное управление соединением и позволяет обращаться к данным нескольким компонентам одновременно.
Свойство connectionstring предназначено для хранения информации о соединении с объектом ADO. В нем через точку с запятой перечисляются все необходимые параметры. Как минимум, это должны быть имена провайдера соединения или удаленного сервера:
Connectionstring:='Remote Server=ServerName;Provider=ProviderName';
 При необходимости указываются путь к удаленному провайдеру:
Connectionstring:='Remote Provider=ProviderName';
и параметры, необходимые провайдеру:
'User Name=User_Name;Password=Password';
Каждый компонент, обращающийся к хранилищу данных ADO самостоятельно, задавая параметры соединения в свойстве Connectionstring, открывает собственное соединение. Чем больше приложение содержит компонентов ADO, тем больше соединений может быть открыто одновременно.
Поэтому целесообразно реализовать механизм соединения ADO через специальный компонент — TADOConnection. Этот компонент открывает соединение, также заданное свойством Connectionstring (см. выше), и предоставляет разработчику дополнительные средства управления соединением.
Компоненты, работающие с хранилищем данных ADO через данное соединение, подключаются к компоненту TADOConnection при помощи свойства
property Connection: TADOConnection;
которое имеет каждый компонент, инкапсулирующий набор данных ADO.
Компонент TADOConnection
Компонент TADOConnection предназначен для управления соединением с объектами хранилища данных ADO. Он обеспечивает доступ к хранилищу данных компонентам ADO, инкапсулирующим набор данных (см. ниже).
Применение этого компонента дает разработчику ряд преимуществ:

  •  все компоненты доступа к данным ADO обращаются к хранилищу данных через одно соединение;
  •  возможность напрямую задать объект провайдера соединения;
  •  доступ к объекту соединения ADO;
  •  возможность выполнять команды ADO;
  •  выполнение транзакций;
  •  расширенное управление соединением при помощи методов-обработчиков событий.

 

Настройка соединения


Перед открытием соединения необходимо задать его параметры. Для этого предназначено свойство
property ConnectionString: WideString;
которое подробно рассматривалось в разд. "Компонент TADOConnection". Добавим лишь, что набор параметров изменяется в зависимости от типа провайдера и может настраиваться как вручную, так и при помощи специального редактора параметров соединения, который вызывается двойным щелчком на компоненте TADOConnection, перенесенным на форму, или щелчком на кнопке в поле редактирования свойства ConnectionString в Инспекторе объектов (2).
Здесь можно настроить соединение через свойство ConnectionString (радиокнопка Use Connection String) или загрузить параметры соединения из файла с расширением udl (радиокнопка Use Data Link File).
Файл UDL (листинг 19.1) представляет собой обычный текстовый файл, в котором указывается название параметра и через знак равенства его значение. Параметры разделяются точкой с запятой.
Листинг 19.1  Демонстрационный файл DBDEMOS.UDL
[oledb]
Everything after this line is an OLE DB initstring
Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Program Files\Common Files\Borland Shared\Data\DBDEMOS.mdb
Если файл параметров соединения отсутствует, настройку придется осуществлять вручную. Для этого следует нажать кнопку Build. В результате появляется диалоговое окно Data Link Properties, в котором можно настроить параметры соединения вручную. Оно представляет собой четырехстраничный блокнот, позволяющий вам этап за этапом задать все необходимые параметры (3).
Первая страница Provider позволяет выбрать провайдер OLE DB для конкретного типа источника данных из числа провайдеров, установленных в системе. Здесь вы видите провайдеры не только для серверов БД, но и служб, установленных в операционной системе. Состав элементов управления следующих страниц зависит от типа источника данных, но различается не так уж сильно. Далее практически везде необходимо задать источник данных (имя сервера, базу данных, файл и т. д.), режим аутентификации пользователя, а также определить имя и пароль пользователя.
Рассмотрим процесс настройки на примере провайдера OLE DB для сервера Microsoft SQL Server.
Следующая страница Connection (4) настраивает источник данных.
На первом этапе требуется выбрать имя сервера из доступных для данного компьютера.
Второй этап определяет режим аутентификации пользователя. Это либо система безопасности Windows, либо собственная система аутентификации сервера. Здесь же надо определить имя и пароль пользователя.
Третий этап предназначен для выбора базы данных сервера.
По окончании настройки источника данных вы можете проверить соединение, нажав кнопку Test Connection.
Теперь перейдем на следующую страницу.
Страница Advanced (5) задает дополнительные параметры соединения. В зависимости от типа хранилища данных некоторые элементы этой страницы могут быть недоступны.
Список Impersonation level определяет возможности клиентов при подключении в соответствии с полномочиями их ролей. В списке могут быть выбраны следующие значения:

  •  Anonymous — роль клиента недоступна серверу;
  •  Identify — роль клиента опознается сервером, но доступ к системным объектам заблокирован;
  •  Impersonate — процесс сервера может быть представлен защищенным контекстом клиента;
  •  Delegate — процесс сервера может быть представлен защищенным контекстом клиента, при этом сервер может осуществлять другие подключения.

Список Protection level позволяет задать уровень защиты данных. В списке могут быть выбраны следующие значения:

  •  None — подтверждение не требуется;
  •  Connect — подтверждение необходимо только при подключении; 
  •   Call — подтверждение источника данных при каждом запросе; 
  •  Pkt — подтверждение получения от клиента всех данных;
  •  Pkt Integrity — подтверждение получения от клиента всех данных с соблюдением целостности;
  •  Pkt Privacy — подтверждение получения от клиента всех данных с соблюдением целостности и защита шифрованием.

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

  • Read — только чтение;
  • ReadWrite — чтение и запись;
  •  Share Deny None — полный доступ всем на чтение и запись;
  •   Share Deny Read — чтение запрещено всем;
  •  Share Deny Write — запись запрещена всем;
  •  Share Exclusive — чтение и запись запрещена всем;
  •  Write — только запись.

Последняя страница All (6) позволяет просмотреть и при необходимости изменить все сделанные настройки (для этого предназначена кнопка Edit Value...) для выбранного провайдера.
После подтверждения сделанных в диалоге настроек из них формируется значение свойства Connectionstring.
Управление соединением
Соединение с хранилищем данных ADO открывается и закрывается при помощи свойства
property Connected: Boolean;
или методов
procedure Open; overload;
procedure Openfconst UserlD: WideString; const Password: WideString); overload;
и
procedure Close;
Метод open является перегружаемым при необходимости использования удаленного или локального соединения. Для удаленного соединения применяется вариант с параметрами UserID и Password.
До и после открытия и закрытия соединения разработчик может использовать соответствующие стандартные методы-обработчики событий:
property BeforeConnect: TNotifyEvent;
property BeforeDisconnect: TNotifyEvent; 
property AfterConnect: TNotifyEvent; 
property AfterDisconnect: TNotifyEvent;
Кроме этого, компонент TADOConnection имеет дополнительные методы-обработчики. После получения подтверждения от провайдера о том, что соединение будет открыто, перед его реальным открытием вызывается метод
TWillConnectEvent = procedure(Connection: TADOConnection; var Connectionstring, UserlD, Password: WideString; var ConnectOptions: TConnectOption; 
var EventStatus: TEventStatus) of object;
 property OnWillConnect: TWillConnectEvent;
Параметр Connection содержит указатель на вызвавший обработчик компонент.
Параметры Connectionstring, userID и Password определяют строку параметров, имя и пароль пользователя.
Соединение может быть синхронным или асинхронным, что и определяется параметром ConnectOptions типа TConnectOption:
type TConnectOption = (coConnectUnspecified, coAsyncConnect);
coConnectunspecified — синхронное соединение всегда ожидает результат последнего запроса;
coAsyncConnect — асинхронное соединение может выполнять новые запросы, не дожидаясь ответа от предыдущих запросов.
Наконец, параметр Eventstatus позволяет определить успешность выполнения посланного запроса на соединение:
type
TEventStatus = (esOK, esErrorsOccured, esCantDeny, esCancel, esUnwantedEvent);
esOK — запрос на соединение выполнен успешно;
esErrorsOccured — в процессе выполнения запроса возникла ошибка;
esCantDeny — соединение не может быть прервано;
esCancel — соединение было прервано до открытия;
esUnwantedEvent внутренний флаг ADO.
Например, в случае успешного соединения можно выбрать синхронный режим работы компонента:
procedure TForml.ADOConnectionWillConnect(Connection: TADOConnection;
 var ConnectionString, UserlD, Password: WideString;
 var ConnectOptions: TConnectOption;
 var Eventstatus: TEventStatus); 
begin if Eventstatus = esOK
then ConnectOptions := coConnectunspecified; 
end;
Кстати, параметр синхронности/асинхронности можно также задать при помощи свойства
ConnectOptions property ConnectOptions: TConnectOption;
После открытия соединения для выполнения собственного кода можно использовать метод-обработчик
TConnectErrorEvent = procedure(Connection:
  TADOConnection; Error: Error;
 var Eventstatus: TEventStatus) of object; 
property OnConnectComplete: TConnectErrorEvent;
Здесь, если в процессе открытия соединения возникла ошибка, параметр Eventstatus будет равен esErrorsOccured, а параметр Error содержит объект ошибки ADO.
Теперь перейдем к вспомогательным свойствам и методам компонента TADOConnection, обеспечивающим соединение.
Для ограничения времени открытия соединения для медленных каналов связи используется свойство
property ConnectionTimeout: Integer;
задающее время ожидания открытия соединения в секундах. По умолчанию оно равно 15 сек.
Также можно определить реакцию компонента на неиспользуемое соединение. Если через соединение не подключен ни один активный компонент, свойство

property KeepConnection: Boolean;
в значении True сохраняет соединение открытым. Иначе, после закрытия последнего связанного компонента ADO, соединение закрывается.
При необходимости провайдер соединения ADO определяется напрямую свойством
property Provider: WideString;
Имя источника данных по умолчанию задается свойством
property DefaultDatabase: WideString;
Но если этот же параметр указан в строке соединения, то он перекрывает собой значение свойства.
При необходимости прямой доступ к объекту соединения OLE DB обеспечивает свойство
property ConnectionObject: _Connection;
При открытии соединения необходимо вводить имя пользователя и его пароль. Появление стандартного диалога управляется свойством
property LoginPrompt: Boolean;
Без этого диалога для задания данных параметров можно использовать свойство Connectionstring, метод open (см. выше) или метод-обработчик
type TLoginEvent = procedure(Sender:TObject; 
Username, Password: string)
of object;
property OnLogin: TLoginEvent;
Свойство
type TConnectMode = (cmUnknown, cmRead, cmWrite, cinReadWrite, cmShareDenyRead, cmShareDenyWrite, cmShareExclusive, cmShareDenyNone);
 property Mode: TConnectMode;
задает доступные для соединения операции:

  • cmUnknown — разрешение неизвестно или не может быть установлено;
  • cmRead — разрешение на чтение;
  • cmwrite — разрешение на запись;
  • cmReadWrite — разрешение на чтение и запись;
  • cmshareDenyRead — разрешение на чтение для других соединений запрещено;
  • cmshareoenywrite — разрешение на запись для других соединений запрещено;
  • cmShareExciusive — разрешение на открытие для других соединений запрещено;
  • cmshareDenyNone — открытие других соединений с разрешениями запрещено.

 

 

Доступ к связанным наборам данных и командам ADO


Компонент TADOconnection обеспечивает доступ ко всем компонентам, которые используют его для доступа к хранилищу данных ADO. Все открытые таким образом наборы данных доступны через индексированное свойство
property DataSets[Index: Integer]: TCustomADODataSet;
Каждый элемент этого списка содержит дескриптор компонента доступа к данным ADO (тип TCustomADODataSet). Общее число связанных компонентов с наборами данных возвращается свойством
property DataSetCount: Integer;
Для этих компонентов можно централизованно установить тип используемого курсора при помощи свойства
type TCursorLocation = (clUseServer, clUseClient); property CursorLocation: TCursorLocation;
Значение clUseClient задает локальный курсор на стороне клиента, что позволяет выполнять любые операции с данными, в том числе не поддерживаемые сервером.
Значение cIUseServer задает курсор на сервере, который реализует только возможности сервера, но обеспечивает быструю обработку больших массивов данных.
Например:
for i := 0 to ADOConnection.DataSetCount — 1 do
 begin
if ADOConnection.DataSets[i].Active = True then ADOConnection.DataSets[i].Close;
ADOConnection.DataSets[i].CursorLocation := clUseClient; end;
Помимо наборов данных компонент TADOConnection обеспечивает выполнение команд ADO. Команду ADO инкапсулирует специальный компонент TADOCommand, который рассматривается ниже. Все команды ADO, работающие с хранилищем данных через это соединение, доступны для управления через индексированное свойство
property Commands[Index: Integer]: TADOCommand
Каждый элемент этого списка представляет собой экземпляр класса
TADOCommand.
Общее число доступных команд возвращается свойством
property CommandCount: Integer
Например, сразу после открытия соединения можно выполнить все связанные команды ADO, реализовав таким образом нечто вроде скрипта:
procedure TForml.ADOConnectionConnectComplete(Connection: TADOConnection; 
const Error: Error; var EventStatus: TEventStatus); 
var i, ErrorCnt: Integer;
 begin
if EventStatus = esOK then
for i := 0 to ADOConnection.CommandCount — 1 do
 try if ADOConnection.Commands[i].CommandText <> 
then ADOConnection.Commands[i].Execute; except
on E: Exception do Inc(ErrorCnt);
  end; 
end;
Однако компонент TADOConnection может выполнять команды ADO самостоятельно, без помощи других компонентов. Для этого используется перегружаемый метод
function Execute(const CommandText: WideString; ExecuteOptions:
TExecuteOptions = []): _RecordSet; overload;
procedure Execute(const CommandText: WideString; 
var RecordsAffected:
Integer; ExecuteOptions: TExecuteOptions = [eoExecuteNoRecords]);
overload;
Выполнение команды осуществляется процедурой Execute (если команда не возвращает набор записей) или одноименной функцией Execute (если команда возвращает набор записей).
Параметр commandText должен содержать текст команды. Параметр RecordsAffected возвращает число обработанных командой записей (если они есть). Параметр
type
TExecuteOption = (eoAsyncExecute, eoAsyncFetch, eoAsyncFetchNonBlocking, eoExecuteNoRecords);
TExecuteOptions = set of TExecuteOption;
задает условия выполнения команды:

  •  eoAsyncExecute — команда выполняется асинхронно (соединение не будет ожидать окончания выполнения команды, а продолжит работу, обработав сигнал о завершении команды, когда он поступит);
  •  eoAsyncFetch — команда получает необходимые записи также асинхронно;
  •  eoAsyncFetchNonBlocking — команда получает необходимые записи также асинхронно, но при этом созданная нить не блокируется;
  •  eoExecuteNoRecords — команда не должна возвращать записи.

Если источник данных принял команду для выполнения и сообщил об этом соединению, вызывается метод-обработчик
TWillExecuteEvent = procedure(Connection: TADOConnection;
var CommandText: WideString; var CursorType: TCursorType; var LockType:
TADOLockType; var ExecuteOptions: TExecuteOptions;
 var EventStatus:
TEventStatus; const Command: _Command;
 const Recordset: _Recordset)
of object;
property OnWillExecute: TWillExecuteEvent;
После выполнения команды вызывается метод-обработчик
TExecuteCompleteEvent = procedure(Connection: TADOConnection; RecordsAffected: Integer; 
const Error: Error; var EventStatus: TEventStatus; 
const Command: _Command;
 const Recordset: _Recordset) of object;
 property OnExecuteComplete: TExecuteCompleteEvent;
Объектошибок ADO
Все ошибки времени выполнения, возникающие при открытом соединении, сохраняются в специальном объекте ADO, инкапсулирующем коллекцию сообщений об ошибках. Доступ к объекту возможен через свойство
property Errors: Errors;
Подробнее об объекте ошибок ADO см. ниже.
 
Транзакции
Компонент TADOconnection позволяет выполнять транзакции. Методы
function BeginTrans: Integer;
 procedure CommitTrans; 
procedure RollbackTrans;
обеспечивают начало, фиксацию и откат транзакции соответственно. Методы-обработчики
TBeginTransCompleteEvent = procedure(Connection: TADOConnection;
TransactionLevel: Integer; 
const Error: Error; 
var EventStatus:
TEventStatus) of object;
property OnBeginTransComplete: TBeginTransCompleteEvent;
TConnectErrorEvent = procedure(Connection: TADOConnection; 
Error: Error;
var EventStatus: TEventStatus) of object;
property OnCornmitTransComplete: TConnectErrorEvent;
вызываются после начала и фиксации транзакции. Свойство
type TIsolationLevel = (ilUnspecified, ilChaos, ilReadUncommitted, ilBrowse, ilCursorStability, ilReadCorranitted, ilRepeatableRead, ilSerializable, illsolated); 
property IsolationLevel: TIsolationLevel;
позволяет задать уровень изоляции транзакции:

  •  IlUnspecif led — уровень изоляции не задается;
  • Iichaos — изменения более защищенных транзакций не перезаписываются данной транзакцией;
  • IlReadUncommitted — незафиксированные изменения других транзакций видимы;
  •  IlBrowse — незафиксированные изменения других транзакций видимы;
  • IlCursorStability — изменения других транзакций видимы только после фиксации;
  •  IlReadCommitted — изменения других транзакций видимы только после фиксации;
  • IlRepeatableRead — изменения других транзакций не видимы, но доступны при обновлении данных;
  • ISerializable — транзакция выполняется изолированно от других транзакций;
  • Ilisolated — транзакция выполняется изолированно от других транзакций.

Свойство
TXactAttribute = (xaCommitRetaining, xaAbortRetaining); property Attributes: TXactAttributes;
задает способ управления транзакциями при их фиксации и откате:

  •  xaCommitRetaining — после фиксации очередной транзакции автоматически начинается выполнение новой;
  •  xaAbortRetaining — после отката очередной транзакции автоматически начинается выполнение новой.

 

Наборы данных ADO


На странице ADO Палитры компонентов Delphi, кроме компонентов соединения есть стандартные компоненты, инкапсулирующие набор данных и адаптированные для работы с хранилищем данных ADO (7). Это компоненты:

  •  TADODataSet — универсальный набор данных;
  •  TАоотаblе — таблица БД;
  •  TADOQuery — запрос SQL;
  •  TAoostoredProc — хранимая процедура.

Как и положено для компонентов, инкапсулирующих набор данных, их общим предком является класс TDataSet, предоставляющий базовые функции управления набором данных (см. гл. II).
Компоненты ADO обладают обычным набором свойств и методов, а необходимый для доступа к данным через ADO механизм наследуют от своего общего предка — класса TCustomADODataSet. Кроме этого, класс TCustomADODataSet содержит ряд общих для всех потомков свойств и методов, рассмотреть которые будет очень полезно. Поэтому сначала мы изучим класс TCustomADODataSet и только потом перейдем к компонентам ADO.
Класс TCustomADODataSet
Класс TCustomADODataSet инкапсулирует механизм доступа к хранилищу данных через ADO. Этот класс наполняет абстрактные методы общего предка TDataSet функциями конкретного механизма доступа к данным.
Поэтому здесь мы рассмотрим только уникальные свойства и методы класса TCustomADODataSet, обеспечивающие работу с ADO.
Соединение набора данных с хранилищем данных ADO осуществляется через компонент TADOConnection (свойство connection) или путем задания параметров соединения через свойство connectionstring (см. выше).
Набор данных
Перед открытием набора данных необходимо установить тип используемой при редактировании записей блокировки. Для этого применяется свойство
type TADOLockType = (ItUnspecified, ItReadOnly, ItPessimistic, ItOptimistic, ItBatchOptimistic); property LockType: TADOLockType;
ItUnspecified — блокировка задается источником данных, а не компонентом; 
ItReadOnly — набор данных откроется в режиме только для чтения;
ItPessimistic — редактируемая запись блокируется на все время редактирования до момента сохранения в хранилище данных;
ItOptimistic — запись блокируется только на время сохранения изменений в хранилище данных;
ItBatchOptimistic — запись блокируется на время сохранения в хранилище данных при вызове метода updateBatch.
 Примечание 
Для того чтобы установка блокировки сработала, свойство LockType должно быть обязательно модифицировано до открытия набора данных.
Набор данных открывается методом Open и закрывается методом close. Также можно использовать свойство
property Active: Boolean;
Текущее состояние набора данных можно определить свойством
type
TObjectState = (stClosed, stOpen, stConnecting, stExecuting, stretching);
TObjectStates = set of TObjectState;
property RecordsetState: TObjectStates;
Набор данных в компонентах ADO основан на использовании объекта набора записей ADO, прямой доступ к этому объекту возможен при помощи свойства
property Recordset: _Recordset;
Но поскольку все основные методы интерфейсов объекта набора записей ADO перекрыты методами класса, в обычных случаях прямой доступ к объекту вам не понадобится. После обновления набора данных вызывается метод-обработчик
TRecordsetEvent = procedure(DataSet: TCustomADODataSet; const Error: Error;
 var EventStatus: TEventStatus) of object; property OnFetchComplete: TRecordsetEvent;
где Error — ссылка на объект ошибки ADO, если она возникла.
Если же набор данных работает в асинхронном режиме, при обновлении вызывается метод-обработчик
TFetchProgressEvent = procedure(DataSet: TCustomADODataSet;
Progress, MaxProgress: Integer;
var EventStatus: TEventStatus) of object; 
property OnFetchProgress: TFetchProgressEvent;
где параметр Progress показывает долю выполнения операции.
Курсор набора данных
Для набора данных ADO в зависимости от его назначения можно выбрать тип и местоположение используемого курсора. Местоположение курсора задается свойством
type TCursorLocation = (clUseServer, clUseClient); property CursorLocation: TCursorLocation;
Курсор может находиться на сервере (CIUseServer) или на клиенте (CIUseClient).

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

При использовании клиентского курсора необходимо дополнительно установить свойство
TMarshalOption = (moMarshalAll, moMarshalModifiedOnly); property MarshalOptions: TmarshalOption
которое управляет обменом данных клиента с сервером. Если соединение с сервером быстрое, можно использовать значение moMarshalAll, разрешающее возврат серверу всех записей набора данных. В противном случае для ускорения работы компонента можно применить свойство moMarshalModifiedOnly, обеспечивающее возврат только модифицированных клиентом записей.
Тип курсора определяется свойством
TCursorType = (ctUnspecified, CtOpenForwardOnly, ctKeyset, ctDynamic,
ctStatic);
property CursorType: TCursorType;
ctunspecified — курсор не задан, тип курсора определяется возможностями источника данных;
ctOpenForwardOnly — однонаправленный курсор, допускающий перемещение только вперед; используется при необходимости быстрого одиночного прохода по всем записям набора данных;
ctKeyset — двунаправленный локальный курсор, не обеспечивающий просмотр добавленных и удаленных другими пользователями записей;
 ctDynamic — двунаправленный курсор, отображает все изменения, требует наибольших затрат ресурсов;
ctStatic — двунаправленный курсор, полностью игнорирует изменения, внесенные другими пользователями.
Примечание
Если курсор расположен на клиенте (CursorType = ciusedient), то для него доступен только один тип — ctStatic.
Соответственно до и после каждого перемещения курсора в наборе данных вызываются методы - обработчики:
TRecordsetReasonEvent = procedure(DataSet: TCustomADODataSet;
const Reason: TEventReason; 
var EventStatus: TEventStatus) of object;
property OnWillMove: TRecordsetReasonEvent;
и
TP.ecordsetErrorEvent = procedure(DataSet: TCustomADODataSet; const --eason: TEventReason;
const Error: Error; var EventStatus: TEventStatus) if object; 
property OnMoveComplete: TRecordsetErrorEvent;
где параметр Reason позволяет узнать, какой метод вызвал это перемещение.

 

 
На главную | Содержание | < Назад....Вперёд >
С вопросами и предложениями можно обращаться по nicivas@bk.ru. 2013 г. Яндекс.Метрика