Теперь создадим новый проект - будущее клиентское приложение. Если он разрабатывается на том же компьютере, где создавался сервер приложений, можно добавить его к уже существующей группе проектов. В общем же случае клиентское приложение не обязано разрабатываться на том же компьютере, что и сервер (в общем случае сервер может вообще функционировать на платформе, отличной от Windows).
Создадим главную форму, поместим на нее компонент TCorbaConnection. Установим значения его свойств такими, как на рис. 6:
Рис. 6. Содержимое удаленного модуля данных
Здесь HostName - IP-адрес компьютера, на котором должен выполняться CORBA-сервер, ObjectName - имя удаленного модуля данных (CORBA-объекта; в общем случае их может быть в одном сервере несколько). Свойство RepositoryId - идентификатор конкретной реализации CORBA-объекта в формате <имя исполняемого файла>/<имя объекта>. Возможен и другой формат этой строки:
IDL:<имя исполняемого файла>/<имя объекта>:<версия>.
Теперь свойство Connected компонента CorbaConnection1 можно установить равным True (или произвести установку этого свойства равным True на этапе выполнения в момент создания формы клиентского приложения).
Теперь можно поместить на форму компонент TClientDataSet, установить значение его свойства RemoteServer равным CorbaConnection1, а затем поместить на форму компонент TDataSource и связать его с компонентом TClientDataSet.
Компонент TClientDataSet предназначен для хранения данных, полученных от сервера приложений, в кэше клиента, и, будучи потомком компонента TDataSet, обладает, подобно компонентам TTable и TQuery, как навигационными методами, так и методами, осуществляющими редактирование данных. Кроме того, этот компонент обладает методами SaveToFile и LoadFromFile, позволяющими сохранять данные из кэша в файле и восстанавливать их оттуда, реализуя так называемую "briefcase model" - модель обработки данных, основанную на том, что "тонкий" клиент осуществляет редактирование данных по большей части при отсутствии соединения с сервером, используя лишь кэш или локальные внешние устройства, и лишь иногда соединяется с сервером приложений для передачи ему измененных данных с целью дальнейшей обработки.
Добавим на форму компоненты TDBGrid, TDBImage, TDBNavigator и свяжем их с DataSource1. Свойство DataField компонента DBImage1 установим равным IMAGE. Добавим также две кнопки (рис. 7:).
Рис. 7. Интерфейсные элементы клиентского приложения
Теперь можно установить нужное значение свойства ProviderName компонента TClientDataSet, выбрав его из выпадающего списка объектов, экспортированных из удаленного модуля данных сервера приложений (так как сервер приложений выбран, все его доступные через интерфейс свойства становятся видны в среде разработки). Далее нужно установить значение свойства Active компонента TClientDataSet равными true (рис. 8).
Рис. 8. Главная форма клиентского приложения
Отметим, что если пользователь редактирует данные в клиентском приложении, они не переносятся непосредственно на сервер баз данных, а вместо этого кэшируются. Фактически компонент TClientDataSet осуществляет доступ к содержимому кэша и при необходимости инициирует добавление в него записей и перенос их обратно на сервер. Идея кэширования данных не нова: использовать его можно и в случае использования классической двухзвенной архитектуры (например, установив равным True свойство CachedUpdates компонента TTable или TQuery). Однако для "тонких" клиентов, связь которых с сервером приложений может осуществляться самыми разными способами, в том числе с помощью каналов, не обеспечивающих стабильную постоянную связь (например, с помощью модемного соединения по телефонной линии), этот способ редактирования данных является основным. На нем же основана так называемая briefcase model (модель работы с данными без постоянного соединения), когда пользователи лишь время от времени соединяются с сервером приложений для синхронизации данных, а подавляющую часть времени работают с кэшем и локальными внешними устройствами, периодически сохраняя и восстанавливая свои данные с помощью методов SaveToFile и LoadFromFile компонента TClientDataSet .
Отметим, что в Delphi 4 компонент TСlientDataSet может содержать кэшированные данные не только из одной, но и из нескольких связанных между собой на сервере приложений таблиц. В нашем случае исходные таблицы CLIENTS и HOLDINGS связаны соотношением Master-Detail на сервере приложений. В результате этого в наборе данных, кэшируемом компонентом ClientDataSet, помимо полей, соответствующих реальным полям таблицы CLIENTS, имеется поле типа TDataSetField, реально соответствующее detail-записям таблицы HOLDINGS, связанным с текущей записью таблицы CLIENTS. Иными словами, компонент TClientDataSet эмулирует так называемые "вложенные" таблицы, характерные для некоторых объектно-ориентированных СУБД.
Для инициации процесса реального сохранения в базе данных используется метод ApplyUpdates компонента TClientDataSet. В качестве параметра этот метод использует целое число, равное максимально допустимому числу ошибок сервера, после которого следует прекратить попытки физического сохранения данных (значение -1 означает, что следует пытаться сохранить все данные независимо от числа ошибок).
Почему предусмотрена возможность ошибок сервера? Ответ очевиден - клиентское приложение может в общем случае ничего не знать о правилах ссылочной целостности и иных ограничениях, содержащихся на сервере баз данных, и только попытка физического сохранения изменений в базе данных может выявить их нарушения (отметим, что на клиентской рабочей станции может даже не быть библиотеки BDE).
Для сохранения данных из кэша на сервере баз данных создадим обработчики событий, связанных с нажатием на кнопки "Apply" и "Cancel":
procedure TForm1.Button1Click(Sender: TObject); begin ClientDataSet1.ApplyUpdates(-1); end; procedure TForm1.Button2Click(Sender: TObject); begin ClientDataSet1.CancelUpdates; end;
Далее можно запустить и протестировать клиентское приложение. Обратите внимание: показания счетчика соединений на главной форме сервера приложений должны измениться, так как теперь у сервера приложений два клиента - среда разработки и запущенное приложение (рис. 9).
Рис. 9. "Тонкий" клиент на этапе выполнения
Если щелкнуть мышью на колонке Table2 компонента TDBGrid, появится дополнительная форма с detail-записями, соответствующими текущей master-записи. Их также можно редактировать - при выполнении метода ApplyUpdates изменения в них будут сохранены.
При желании можно с помощью утилиты SQL Monitor, запущенной на том же компьютере, что и сервер приложений, проследить, какие именно запросы созданный нами сервер приложений направляет серверу баз данных.
Отметим, что для переноса клиентского приложения на другой компьютер следует вместе с исполняемым файлом скопировать библиотеку dbclient.dll либо в каталог Windows\System, либо в тот же каталог, где находится исполняемый файл. Библиотеку Borland Database Engine на этот компьютер устанавливать не нужно - "тонкий" клиент к ней не обращается.
CORBA-объект, также как и COM-объект, может обладать произвольным набором свойств и методов, которые можно добавить, редактируя библиотеку типов и код реализации. В частности, можно добавить и метод, осуществляющий доступ к базе данных с помощью пароля. Реализация его может, к примеру, иметь следующий вид:
procedure TMyRDM.Login(username, password: OleVariant); begin Database1.Connected:=false; Database1.params.Values['Password']:=password; Database1.params.Values['User Name']:=username; Database1.Connected:=true; Table1.Open; Table2.Open; end;
Соответствующий клиентский код имеет в этом случае вид:
procedure Tform1.ButtonLoginClick(Sender: TObject); begin Form1.ClientDataSet1.Close; Form1.MIDASConnection1.AppServer.Login(Edit1.Text,Edit2.Text); Form1.ClientDataSet1.ProviderName:='Table1'; Form1.ClientDataSet1.Open; end;
Отметим также, что создание CORBA-клиентов в виде активных форм возможно точно так же, как и создание COM-клиентов. Наиболее простым способом можно это сделать, выделив все интерфейсные элементы и сохранив их в виде шаблона (Component/Create ComponentTemplate), который позже можно поместить на вновь созданную активную форму. Далее следует в поставку ActiveX включить dbclient.dll, осуществить эту поставку на какой-нибудь web-сервер и попробовать протестировать полученный ActiveX (рис. 10).
Рис. 10. "Тонкий" клиент в виде активной формы на этапе выполнения
Как мы убедились, создание CORBA-серверов и клиентов с помощю Delphi очень напоминает создание COM-серверв и клиентов аналогичного назначения. В принципе легко можно COM-серверы превращать в CORBA-серверы, просто выбрав соответствующую опцию в контекстном меню редактора кода и используя, таким образом, одну и ту же реализацию для разных технологий распределенных вычислений.
Отметим, что создание CORBA-серверов и клиентов с помощю C++Builder осуществляется неколько по-другому и напоминает скорее не создание COM-серверов и клиентов, а создание DCE-серверов и клиентов с помощью кодогенераторов Entera, то есть традиционный способ генерации клиентского и серверного stub-кода на основе IDL-описания интерфейсов сервера. Об этом будет более подробно рассказано в последующих статьях данного цикла.
<< Назад | Содержание | Вперед >>