Borland Kylix: работа с БД

Продолжение цикла статей, посвященных среде кросс-платформенной разработки Borland Kylix. В этой статье обсуждаются механизм работы с базами данных dbExpress и перенос Windows-приложений баз данных под Linux.


*Окончание. Начало см. "BYTE/Россия" № 8/2001.

Мы продолжаем цикл статей, посвященных новой среде кросс-платформенной разработки Borland Kylix. В этой статье мы коснемся внутренних механизмов работы с базами данных, а конкретно - архитектуры dbExpress и библиотеки компонентов DataCLX, а также рассмотрим проблемы переноса Windows-приложений баз данных под Linux. Итак, по порядку.

Механизм dbExpress

До появления Kylix пакет Delphi для Windows предлагал несколько механизмов доступа к базам данных - ADO, Borland Database Engine (BDE) и InterBase Express. Однако в среде Linux ни один из этих механизмов недоступен, поэтому Borland разработала новую кросс-платформенную технологию доступа к данным - dbExpress, работающую как в Windows (Delphi 6), так и в Linux (Kylix).

Механизм dbExpress представляет собой набор небольших по размеру драйверов, предназначенных для работы с серверными SQL-БД. Каждый драйвер для Linux, как уже говорилось, представляет собой файл с расширением SO, который должен быть привязан к создаваемому приложению. В Windows-версии драйверы представлены DLL-библиотеками. Kylix включает драйверы для работы с MySQL и Interbase (во всех версиях), в версии Server Developer дополнительно предлагаются драйверы для Oracle и DB2.

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

Альтернативой однонаправленным НД выступают клиентские наборы данных, работа с которыми осуществляется с использованием компонента ClientDataSet. Клиентские наборы данных используются для отображения данных. При работе с клиентским НД выбранные по запросу записи хранятся в памяти, что позволяет кэшировать изменения, осуществлять навигацию в любом направлении и т.д. С помощью компонента ClientDataSet можно осуществлять доступ к данным в соответствии со схемой провайдер/ресолвер (provider/resolver).

Механизм провайдер/ресолвер

Механизм провайдер/ресолвер отвечает за выдачу данных по запросу пользователя и проведение изменений в БД. В этом механизме можно выделить две основные части:

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

Ресолвер. Эта часть обеспечивает внесение изменений в базу данных. При обновлении базы данных серверу передается протокол изменений, в соответствии с которым начинается транзакция и проводятся изменения в БД.

Как и любой другой механизм доступа к данным, dbExpress требует наличия на стороне клиента специального ПО от разработчика баз данных. Кроме того, для работы приложения необходим драйвер базы данных и два конфигурационных файла - dbxconnections.conf и dbxdrivers.conf. Как видим, это гораздо более компактный набор, чем тот, что требовался при работе с BDE, когда помимо драйвера БД для работы приложения нужно было установить набор библиотек, включая основную библиотеку BDE - Idapi32.dll.

dbExpress в сравнении с другими механизмами

Рассмотрим различия между dbExpress и другими механизмами доступа к данным - ADO, BDE, и клиентом InterBase. Выделим три вида различий. Прежде всего механизмы различаются на уровне взаимодействия приложения с сервером баз данных. Кроме того, различаются и компоненты, непосредственно реализующие тот или иной механизм. Все компоненты для работы с базами данных можно разделить на две группы: одни отвечают за связь с БД, другие служат для работы с наборами данных. Несмотря на такую специфику dbExpress, как использование однонаправленных курсоров, различия на уровне наборов компонентов не очень значительны, так как с точки зрения программной реализации группы компонентов для разных механизмов происходят от одних и тех же классов-предков.

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

Взаимодействие с сервером БД

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

1. dbExpress обеспечивает более простой и быстрый доступ к удаленным БД благодаря использованию однонаправленных наборов данных.

2. Так же, как и BDE, dbExpress обрабатывает пользовательские запросы и хранимые процедуры, однако понятие открытия базы данных в новом механизме отсутствует (в BDE открытие таблицы БД не только занимало большую часть ресурсов на стороне клиента, но и блокировало ресурсы сервера).

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

4. BDE кэширует метаданные, делая их доступными в последующих запросах. dbExpress этого не делает, а работа с метаданными на этапе проектирования осуществляется с использованием основного механизма доступа к данным.

5. При работе с удаленными SQL-базами данных через BDE время обращения к базе данных увеличивается за счет выполнения внутренних запросов, обеспечивающих навигацию по таблицам, доступ к blob-объектам и получение метаданных. dbExpress выполняет только запросы пользователей, отсутствие дополнительных операций помогает оптимизировать доступ к БД.

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

7. dbExpress не поддерживает локальные базы данных типа Paradox, dBase или FoxPro.

8. dbExpress содержит драйверы для таких СУБД, как InterBase, Oracle, DB2 и MySQL. Для использования других серверов существует три возможности: перенос данных в формат одной из поддерживаемых СУБД, написание собственного драйвера или же использование драйверов сторонних разработчиков для работы с вашей СУБД.

Компоненты для работы с базами данных

Компоненты dbExpress можно найти на соответствующей закладке палитры компонентов Kylix. Они, подобно другим компонентам доступа к данным, являются наследниками базовых классов TDataSet и TCustomConnection, а, следовательно, входящие в них свойства, методы и события по большей части одинаковы.

Fig.N
Рис. 1. Закладка dbExpress палитры компонентов Kylix.

В таблице перечислены основные невизуальные компоненты работы с базами данных, применяемые в InterBase Express, BDE и ADO в среде Windows, и соответствующие им компоненты dbExpress, используемые в Linux и в кросс-платформенных приложениях.

Компоненты доступа к данным, используемые различными механизмами

InterBase Express BDE ADO dbExpress
TIBDatabase TDatabase TADOConnection TSQLConnection
TIBTable Ttable TADOTable TSQLTable
TIBQuer TQuery TADOQuery TSQLQuery
TIBStoredPro TstoredProc TADOStoredProc TSQLStoredProc
TIBDataSet - TADODataSet TSQLDataSet
 

Остановимся более подробно на различиях между компонентами BDE и соответствующими компонентами dbExpress.

Эквивалент входящего в BDE компонента TDatabase - это TSQLConnection. Оба они предназначены для установления соединения с реальной базой данных. В dbExpress изначально предопределено несколько видов соединений: DB2Connection, IBLocal, MySQLConnection и OracleConnection. Они перечислены в свойстве ConnectionName компонента TSQLConnection.

Компоненту BDE TTable соответствует компонент TSQLTable. Основное различие состоит в том, что в TSQLTable возвращает однонаправленный нередактируемый набор данных. Аналогичным образом компоненту BDE TQuery соответствует TSQLQuery, также возвращающий однонаправленный НД.

Компоненту BDE TStoredProc соответствует компонент dbExpress TSQLStoredProcedure, как и предыдущие два компонента, возвращающий однонаправленный НД. При переносе под Linux приложений баз данных, использующих этот компонент, следует учитывать, что различные СУБД имеют свои диалекты SQL, и при переходе на другой сервер баз данных может возникнуть проблема с выполнением SQL-выражений из хранимых процедур.

Кроме перечисленных компонентов следует также остановиться и на компонентах TSQLDataSet и TSQLClientDataSet. Компонент TSQLDataSet объединяет в себе возможности компонентов TSQLTable, TSQLQuery и TSQLStoredProcedure.

Компонент TSQLClientDataSet ѕ это комбинация компонентов TSQLDataSet и TClientDataSet, обеспечивающая работу с клиентским набором данных. Хотя компоненты TSQLTable, TSQLQuery и TSQLStoredProcedure возвращают однонаправленные НД, вы можете связать их с TClientDataSet через компонент TDataSetProvider и получить результат, аналогичный использованию TSQLClientDataSet.

Пользовательский интерфейс

Основное различие на этом уровне определяется тем, как компоненты работают с данными. Если вы используете только наборы данных dbExpress, вам придется приспосабливать интерфейс к ограничениям, свойственным однонаправленным НД. То есть вам придется удалить элементы управления, предназначенные для возврата к предыдущим записям; также невозможно будет просматривать записи в виде таблицы (например, с использованием TDBGrid) - dbExpress не буферизует данные, и в каждый момент времени просматривать можно только одну запись.

Если же вы работаете c клиентским НД, то элементы управления, предназначенные для редактирования записей и навигации по НД, удалять не нужно. Достаточно лишь изменить их свойства, чтобы связать их с компонентом клиентского НД. Также следует обратить внимание на способ внесения изменений в базу данных. Большинство компонентов НД в Windows записывает изменения в базу данных автоматически при выполнении метода Post. Клиентские же наборы данных используют для этих целей механизм кэшированных изменений.

Перенос Windows-приложений баз данных под Linux

Процесс переноса приложений баз данных в Linux можно представить как последовательность следующих действий. Первый шаг заключается в переносе самих данных в формат, поддерживаемый dbExpress. Если вы работали с версией Delphi 5 Enterprise, то можете легко перенести данные из формата локальных таблиц (Paradox, dBase, FoxPro), например в формат InterBase, используя для этого утилиту DataPump.

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

На данном этапе создается новый модуль данных в среде Kylix. Для каждого НД из исходного проекта в созданный модуль данных добавляются соответствующий компонент набора данных dbExpress и компоненты TDataSetProvider и TClientDataSet. Затем компоненты TDataSetProvider, TClientDataSet, компонент набора данных и компонент источника данных связываются в соответствии со схемой, изображенной на рис. 2.

Fig.2 Рис. 2. Схема связи компонентов dbExpress.

Свойство ProviderName компонента TClientDataSet должно указывать на компонент TDataSetProvide. Свойство DataSet компонента TDataSetProvider должно указывать на компонент набора данных dbExpress. Свойство DataSet компонента источника данных должно указывать на клиентский НД.

Теперь необходимо установить соответствие между свойствами исходных и новых компонентов. Здесь возможны три следующих варианта.

1. Исходный компонент - TTable, TADOTable или TIBTable. В этом случае необходимо, во-первых, дать новому компоненту такое же имя, которое имел исходный компонент, а во-вторых, сопоставить всем свойствам, реализующим связь master-detail, определяющие индексы. Свойства, управляющие фильтрацией данных, должны быть заданы в компоненте клиентского НД.

2. Исходный компонент - TQuery, TADOQuery или TIBQuery. В этом случае свойства SQL, Params (или Parameters, в зависимости от используемого механизма) нужно сопоставить свойства DataSource, если используется связь master-detail.

3. Исходный компонент - TStoredProc, TADOStoredProc или TIBStoredProc. При работе с этим компонентом нужно обратить внимание на имя компонента и свойство Params.

Для каждого компонента связи с БД из исходного проекта (TDatabase, TIBDatabase или TADOConnection) добавьте в новый модуль данных компонент TSQLConnection. Этот компонент необходимо добавить и для всех серверов БД, соединение с которыми устанавливается без компонента соединения, а посредством, например, указания в BDE псевдонима БД в свойстве DatabaseName любого компонента НД. Затем эти компоненты необходимо связать между собой: свойство SQLConnection компонента набора данных должно указывать на соответствующий компонент TSQLConnection.

В каждом компоненте TSQLConnection нужно определить параметры соединения с базой данных. Для этого используется инструмент Connection Editor, вызываемый двойным щелчком мыши на компоненте. Если вы переносили данные из одного формата в другой на первом этапе, то нужно будет заново установить все параметры соединения с сервером. Если же вы не переходили на другой сервер БД, то нужно будет просто обновить параметры согласно следующим правилам:

  1. Для компонента TDatabase нужно обновить значения свойств Params и TransIsolation.
  2. Для компонента TADOConnection должны обновляться свойства ConnectionString и IsolationLevel.
  3. Для компонента TIBDatabase при пересмотре параметров соединения нужно использовать значения свойств DatabaseName и Params.
  4. Если для соединения с БД не используются конкретные компоненты, то данные о параметрах соединения нужно брать из свойства ConnectionString компонента НД или из информации о псевдониме базы данных в BDE.

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

Сложность процесса переноса приложения баз данных из Windows в Linux зависит от многих параметров. Во-первых, конечно, это сложность исходного приложения, его масштабы. Важно также, поддерживается ли механизмом dbExpress формат самих данных, используемый в исходном приложении. И разумеется, сложность процедуры зависит от того, насколько грамотно было разработано исходное приложение и, соответственно, какое количество исправлений придется вносить при переносе.