Множество модулей данных – одно соединение
Множество модулей данных – одно соединение
Автор: Bill Todd (The Database Group, Inc)WEB-сайт: http://www.programme.ruПеревод: Олег Мотов
При создании многоуровневых приложений в предыдущих версиях Delphi многие разработчики сталкивались с одной проблемой – трудностью размещения всех необходимых компонентов доступа к данным в одном модуле данных. Решение заключалось в том, чтобы использовать несколько удаленных модулей данных.
Первая проблема этого решения состоит в том, что клиентскому приложению необходимо отдельное соединение для каждого модуля данных на сервере приложений. А это – нагрузка на системные ресурсы и на клиенте и на сервере.
Вторая проблема состоит в том, что удаленные модули данных, относящиеся к одному клиенту, абсолютно ничего не знают друг о друге. Например, не существует способа из одного модуля данных вызвать метод другого модуля данных, относящегося к тому же клиенту.
Delphi 6 решает эти проблемы, позволяя клиентскому приложению использовать одно соединение для многих модулей данных на сервере приложений. Делается это не совсем тривиально – только перетаскивания компонентов и запуска «мастеров» недостаточно. Чтобы построить приложение, которое использует разделяемое соединение, придется добавить кое-какие интерфейсы и свойства в библиотеку типов на сервере приложений. Впрочем, достаточно один раз разобраться, как это делается – и в дальнейшем разработка приложений, использующих одно соединение для многих модулей данных, становится несложной.
Лучший способ понять этот процесс состоит в том, чтобы пройти через построение демонстрационного приложения, что мы и сделаем в этой статье. В этой статье подразумевается, что читатель знает, как строить многоуровневое приложение в Delphi 5 с использованием компонентов MIDAS.
Построение сервера
Чтобы построить сервер, создайте новый проект и добавьте к нему удаленный модуль данных. В нашем приложении используется демонстрационная база данных InterBase, а для соединения с базой данных применяется dbExpress. На рис. 1 показан законченный модуль данных. Он содержит компоненты SQLConnection, SQLDataSet и DataSetProvider.
Рисунок 1. Удаленный модуль данных employee
В компоненте SQLConnection, названном EmpConn, свойство DriverName установлено в InterBase. Свойство компонента Params изменено так, чтобы в нем содержался правильный путь к демонстрационной базе данных InterBase. Если вы загрузите демонстрационное приложение, перед запуском надо будет изменить этот путь. Демонстрационное приложение доступно для загрузки, подробности см. в конце статьи.
В компоненте SQLDataSet, названном EmpDs, свойство SQLConnection указывает на компонент подключения EmpConn. Свойству CommandText присвоена команда ‘SELECT * FROM Employee’.
В компоненте DataSetProvider (EmpProv) свойство DataSet указывает на EmpDs.
Далее следует добавить второй удаленный модуль данных к проекту сервера. Второй удаленный модуль данных изображен на рис. 2, он содержит один компонент SQLDataSet (CustDs) со значением ’SELECT * FROM Customer’ свойства CommandText. Модуль данных также содержит DataSetProvider (CustProv), связанный с SQLDataSet.
Рисунок 2. Удаленный модуль данных customer
Теперь нужно добавить необходимые интерфейсы и свойства в библиотеку типов сервера приложений. На рис. 3 показан редактор Type Library с развернутым интерфейсом IEmployeeDm. Чтобы использовать одно разделяемое соединение для доступа ко многим удаленным модулям данных, один из модулей должен быть назначен главным, а все другие модули будут дочерними. В этом примере удаленный модуль данных employee будет главным, а удаленный модуль данных customer дочерним.
Для каждого дочернего модуля данных вы должны добавить свойство, доступное только для чтения в интерфейс главного удаленного модуля данных. На рис. 3 в интерфейс модуля данных employee было добавлено свойство CustomerRdm типа ICustomerDm (интерфейс дочернего модуля данных). Интерфейс дочернего модуля данных ICustomerDm, появляется в раскрывающемся списке типов, так что вам остается лишь выбрать его из списка.
Рисунок 3. Свойство дочернего удаленного модуля данных, добавленное к интерфейсу главного модуля данных
Это – единственное изменение, которое нужно сделать в библиотеке типов сервера приложений, чтобы воспользоваться преимуществами разделяемого соединения.
Одно из достоинств этой технологии – способность любого экземпляра дочернего модуля данных обратиться к интерфейсу главного модуля данных того же соединения. Для этого к интерфейсу каждого дочернего удаленного модуля данных нужно добавить еще одно свойство. Легче всего это сделать, добавив новый интерфейс в библиотеку типов, затем добавить к нему необходимое свойство и использовать этот интерфейс в качестве предка всех дочерних модулей данных.
На рис. 4 показан редактор Type Library с новым интерфейсом IChildDm типа IAppServer. В этот интерфейс добавлено свойство EmployeeRdm типа IEmployeeDM. Затем свойство Parent Interface интерфейса ICustomerDm было изменено на IChildDm. Меняя родительский интерфейс, вы позволяете интерфейсу ICustomerDm унаследовать свойство EmployeeRdm из интерфейса IChildDm. Такую же замену свойства Parent Interface следует сделать в каждом дочернем удаленном модуле данных.
Рисунок 4. Интерфейс IChildDm со свойством EmployeeRdm
После нажатия на кнопку Refresh и закрытия редактора Type Library настало время добавить код к методам чтения и записи добавленных нами свойств. Перейдем в раздел инициализации модуля (unit) дочернего модуля данных. Там вы увидите тот код, который ниже показан в комментарии и помечен "Before:" (он создан автоматически). Измените этот код, чтобы получилось примерно так:
// Before:
// TComponentFactory.Create(ComServer, TCustomerDm, _CustomerDm, ciInternal, tmApartment);
// After:
CustRdmFactory := TComponentFactory.Create(ComServer, TCustomerDm,
Class_CustomerDm, ciInternal, tmApartment);
// В разделе interface модуля следует добавить переменную CustRdmFactory,
// чтобы сохранить ссылку на экземпляр фабрики компонентов, возвращаемую
// вызовом TcomponentFactory.Create:
var
CustRdmFactory: TComponentFactory;
begin
Result := CustRDMFactory.CreateCOMObject(nil) as ICustomerDm;
Result.EmployeeRdm := Self;
end;
begin
Result := FEmployeeRdm;
end;
procedure TCustomerDm.Set_EmployeeRdm(const Value: IEmployeeDm);
begin
FEmployeeRdm := Value;
end;


Скачать демонстрационный пример DelphiWorld 6.0
Отправить комментарий