BERDAFLEX Software Systems
Главная > Delphi > Использование TClientDataset в двухуровневых приложениях. Часть 3

Секреты Delphi. Использование TClientDataset в двухуровневых приложениях. Часть 3

История переиздания
Издание 1.0 2004.06.02 Сергей Бердачук

Наконец настало время первых опытов. К сожалению, не удалось найти оригинальный код демонстрационных компонент Дана Мишера, так что придется воспользоваться созданной несколько лет назад на их базе компонентой TBS_ClientDataset.

Скачать библиотеку с данной компонентой можно по адресу: bs.zip. (данная библиотека компонент распространяется бесплатно и содержит исходные коды) Для данного примера так же воспользуемся еще одной компонентой TBS_ADODataset данной библиотеки.

TBS_ClientDataset для Delphi 5 является наследником стандартной компоненты TClientDataset.

Создадим простой проект в Delphi содержащих одну форму frmMain и два модуля данных dmClient и dmRemote. Развивая тему использования сервера БД Oracle 9i Lite, воспользуемся демонстрационной базой данных POLITE. При отсутствии Oracle 9i Lite можно воспользоваться демонстрационной базой данных ..\Borland Shared\Data\DBDEMOS.mdb, входящей в пакет поставки Delphi.

Наиболее простым способом соединения с базой данных в данном случае будет использование компонент ADO. Для соединения с сервером в модуль dmRemote добавим компоненту TADOConnection. При стандартной установке сервера Oracle 9i Lite алиас ODBC соединения POLITE должен быть прописан автоматически. Если для установки использовался клиентский CD, то придется создать его самостоятельно. Для настройки соединения нажмем кнопку «…» свойства ConnectionString и выберем режим использования строки соединения см. рис 1.

Рисунок 1. 1 Выбор типа соединения компоненты TADOConnection

1 Выбор типа соединения компоненты TADOConnection

Информацию по дальнейшей настройке можно найти в статье: "Секреты Delphi. Соединение с базами данных при помощи компонент ADO".

Добавим в этот же модуль компоненту TBS_ADODataset палитры компонент BS (назовем ее rdsDept).

Свяжем свойство «Connection» с компонентой TADO_Connection. Для настройки SQL Текста нажмем кнопку «…» свойства CommandText и в появившемся SQL редакторе введем запрос к таблице отделов см. рис 2.

Рисунок 2. Редактор SQL запросов

Редактор SQL запросов

Основным отличием компоненты TBS_ADODataset от TADODataset, наследником которой она является, является наличие дополнительного свойства «UniqueFields». В данное свойство через точку с запятой можно прописать список полей, которые будут уникально идентифицировать текущую запись. Это требуется для обеспечения возможности редактирования традиционно Read Only наборов данных, а так же в случаях, если первичные ключи для выбранного сервера БД определяются некорректно. Если, данное свойство не заполнять, то будет вызываться стандартная функция PSGetKeyFields интерфейса IProviderSupport компоненты TADODataset.

Добавляем в модуль dmRemote компоненту TDatasetProvider палитры компонент midas и связываем ее свойство «Dataset» с добавленной ранее компонентой rdsDept. Получим следующую картину, см рис 3.

Рисунок 3. Модуль данных dmRemote

Модуль данных dmRemote

Свойство «ResolveToDataset» устанавливаем в значение «false», что позволит передать управление процессом подтверждения изменений встроенной компоненте TSQLResolver, которая передает изменения сразу компоненте, которая связана с сервером базы данных, в данном случае это dbConnection. Это позволяет исключить необходимость использования дополнительных компонент (например TUpdateSQL), скрипты InsertSQL, DeleteSQL и UpdateSQL будут формироваться автоматически.

Свойство «UpdateMode» устанавливаем в значение «upWhereKeyOnly». Пи наличии первичных ключей это существенно повысит скорость поиска записи сервером базы данных во время внесения изменений.

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

procedure TdmRemote.dspDeptGetTableName(Sender: TObject; DataSet: TDataSet;
  var TableName: String);
begin
   TableName:='System.Dept';
end;

Настало время клиентского модуля данных. Добавим в него компоненту TBS_ClientDataSet. В родительском компоненте TClientDataset испльзуется свойство ProviderName для связи с провайдером TDatasetProvider. Но при размещении компонент связки TClientDataset и TdatasetProvider в различных модулях программы, список провайдеров становиться недоступен. Для решения данной проблемы в TBS_ClientDataset добавлено свойство «DataProvider». Устанавливаем данное свойство в dmRemote.dspDept. Реализация метода SetDataProvider позаимствована из статьи Дана Мишера «Using the MIDAS ClientDataSet as a Replacement for Cached Updates».

Теперь появляется возможность открывать полученный набор данных. Добавим в этот же модуль компоненту TDataSource позволяющую связывать наш TClientDataset с элементами управления. Для защиты от случайных изменений данных пользователями, желательно установить значение свойства «AutoEdit» в «false». В результате этих манипуляций клиентский модуль данных будет иметь вид показанный на рис. 4.

Рисунок 4. Модуль данных dmClient

Модуль данных dmClient

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

procedure TdmClient.cdsDeptApplyUpdates;
begin
  if cdsDept.ChangeCount > 0 then
    cdsDept.ApplyUpdates(-1);
end;

procedure TdmClient.cdsDeptAfterDelete(DataSet: TDataSet);
begin
  cdsDeptApplyUpdates();
end;

procedure TdmClient.cdsDeptAfterPost(DataSet: TDataSet);
begin
  cdsDeptApplyUpdates();
end;

procedure TdmClient.cdsDeptBeforeClose(DataSet: TDataSet);
begin
  if (cdsDept.State in [dsInsert,dsEdit]) then
    cdsDept.Post;
end;

В главной форме для примера разместим кнопку открытия, DBGrid и DBNavigator. Пример работы программы показан на рисунке 5

Рисунок 5. Пример созданного приложения

Пример созданного приложения

Для исключения проблем с освобождением ресурсов желательно принудительно закрывать все открытые экземпляры TClientDataset перед завершением работы программы.

procedure TdmClient.DataModuleDestroy(Sender: TObject);
var
  i:integer;
begin
  for i:=0 to Self.ComponentCount-1 do
    if (self.Components[i] is TBS_ClientDataSet) and
       (TBS_ClientDataSet(self.Components[i]).Active) then
      begin
        TBS_ClientDataSet(self.Components[i]).Close;
      end;
end;

Пример созданного проекта можно скачать по адресу: midasdemo1.zip.

В приведенном архиве содержится так же версия демонстрационного проекта для базы данных Microsoft Access DBDEMOS.mdb.

С использованием данной технологии было создано несколько приложений. Данный подход позволил унифицировать технологию доступа к данным. Хочется отметить, что в последних версиях Delphi появилась модифицированная версия данной технологии "Все в одном".

Примеры коммерческих проектов автора с использованием данной технологии:


Rambler's Top100 Рейтинг@Mail.ru