Опубликован: 07.05.2010 | Уровень: специалист | Доступ: платный
Лекция 29:

Многоуровневая архитектура. Создание "тонкого" клиента

< Лекция 28 || Лекция 29: 12
Аннотация: На этой лекции мы рассмотрим создание клиентского приложения в многоуровневой архитектуре баз данных, с механизмом подключения "тонкого" клиента к серверу. Изучим работу компонентов DCOMConnection и ClientDataSet, с помощью которых клиентское приложение подключим к серверу, сделанному в предыдущей лекции.

На прошлой лекции мы рассматривали создание сервера приложений на основе удаленного модуля данных Remote Data Module. Эта лекция посвящена созданию клиентской части многоуровневых приложений на основе технологии DCOM. Связать клиентское приложение с одной таблицей очень просто. Связать две или более таблицы в отношении один-ко-многим несколько сложней, тут есть свои тонкости. Именно такую связь мы и будем делать. Кроме того, мы разберем способ реализации отложенной обработки, когда данные можно сохранить в файл, и при необходимости, загрузить их из файла без соединения с удаленным сервером приложений.

Связь клиентского приложения с удаленным модулем данных организуется одним из компонентов связи, расположенных на вкладке DataSnap Палитры компонентов, а для связи с наборами данных используется компонент ClientDataSet, который находится на вкладке Data Access Палитры компонентов. Каждый ClientDataSet соединяется с одним набором данных (таблица, запрос).

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

Создание клиентского приложения

Начните новый проект. В свойстве Name главной формы напишите fMain, в свойстве Caption напишите "Клиент удаленного сервера", сохраните ее модуль под именем Main, а проект в целом - MyNewClient. На форму поместите три простых панели, сразу же очистив их свойство Caption. У верхней панели в свойстве Align выберите alTop, а в свойстве AutoSize установите True. Поместите на эту панель навигатор DBNavigator с вкладки Data Controls Палитры компонентов.

У нижней панели в свойстве Align выберите alBottom, чтобы она заняла всю нижнюю часть формы. На панель поместите сетку DBGrid и шесть простых кнопок.

Средняя панель в свойстве Align будет иметь значение alClient. На ней помещается только одна сетка DBGrid, которая в свойстве Align также имеет значение alClient. Внешний вид формы представлен на рисунке ниже:

Главная форма клиентского приложения

Рис. 29.1 . Главная форма клиентского приложения

Свойство Name у кнопок переименуйте, соответственно, в:

  • bConnect
  • bRefresh
  • bSaveToDB
  • bUnConnect
  • bSaveToFile
  • bLoadFromFile

Свойство Caption кнопок измените, как на рисунке.

Верхнюю сетку и навигатор позже соединим с главной таблицей LichData, нижняя сетка отобразит данные подчиненной таблицы Telephones.

Для невизуальных компонентов доступа создадим обычный модуль данных. Выберите команду File -> New -> Data Module. В свойстве Name модуля данных укажите fDM, а сам модуль сохраните на диск под именем DM. Не забудьте в главной форме командой File -> Use Unit подключить этот модуль.

Перейдем на вкладку DataSnap. Вы видите целый ряд компонентов, реализующих подключение с удаленным модулем данных различными технологиями. Нам нужен компонент DCOMConnection, который использует технологию DCOM, поместите его в модуль данных. Для краткости обращений к компоненту переименуйте его свойство Name в DCOMC. Теперь нужно подключить его к удаленному серверу. В свойстве ComputerName нужно указать сетевое имя или IP -адрес компьютера, на котором расположен сервер приложений. Поскольку у нас все хранится на одном компьютере, укажем адрес 127.0.0.1, то есть, локальный IP -адрес.

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

MyNewServer.MyRDM

Выберем эту строку. В свойстве ServerGUID автоматически должен появиться уникальный идентификатор сервера. Убедимся, что свойство LoginPrompt установлено в False, чтобы при соединении не запрашивались имя пользователя и пароль, и переведем свойство Connected в True, чтобы физически подключить клиентское приложение к серверу. Если вы все сделали правильно, то соединение произойдет, при этом Windows автоматически загрузит сервер приложений, который мы делали на прошлой лекции. Вот таким простым способом клиентское приложение связывается с удаленным модулем данных. Как видите, компонент содержит минимум необходимых свойств.

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

Компонент ClientDataSet предназначен для:

  • Предоставления удаленных данных, расположенных на сервере приложений;
  • Загрузки данных из локального файла;
  • Сохранение набора (или связанных наборов) данных в локальный файл.

Компонент ClientDataSet является наследником объекта DataSet, как таблицы или запросы, поэтому он имеет почти те же свойства, методы и события, что и эти наборы данных. Например, открытие этого НД можно осуществить как методом Open, так и присвоением True свойству Active. Однако, в связи с удаленным способом связи, имеются и различия. Прежде всего, различие связано с тем, что компонент считывает данные в буфер (или кэш), после чего работает с ними. Выполнение метода Post, к примеру, сохраняет данные не в базе данных на сервере, а в буфере (в оперативной памяти клиентского приложения). Чтобы сохранить эти данные в базу, нужно явно вызвать метод ApplyUpdates. Это позволяет существенно снизить нагрузку на сетевой трафик. Таким способом и реализуется отложенная обработка.

Рассмотрим основные свойства и методы компонента ClientDataSet.

Основные свойства и методы компонента ClientDataSet

Таблица 29.1 . Важные свойства компонента ClientDataSet
Свойство Описание
ChangeCount Содержит количество изменений в буфере. После явного сохранения изменений в базу данных, это свойство содержит 0.
CommandText Содержит текст SQL -запроса, который может быть выполнен методом Execute компонента. Таким образом, можно изменять НД, предоставляемый сервером.
Data Свойство содержит пакет данных, предназначенный для передачи по сети в специальном транспортном формате.
DataSize Размер в байтах пакета Data.
DataSetField При отношении один-ко-многим, свойство у подчиненного ClientDataSet позволяет выбрать специальное поле типа TDataSetField, которое инкапсулирует данные подчиненного НД. Подробней об этом поговорим ниже.
Delta Пакет с измененными данными, которые еще не сохранены на сервере.
FetchOnDemand При значении True (по умолчанию) разрешает компоненту получать очередной пакет данных по мере надобности, например при прокрутке сетки DBGrid.
FileName Может содержать имя файла, в которое при необходимости будет сохранять данные, или считывать их. Если этого имени нет, можно использовать SaveDialog или OpenDialog для получения этого имени от пользователя.
PacketRecords Указывает количество записей, получаемых из серверного НД в одном пакете. По умолчанию равно -1, то есть считываются все записи. Если значение равно 0, то считываются только метаданные.
ProviderName Имя компонента-провайдера на стороне сервера ( DataSetProvider ), который предоставляет доступ к нужному набору данных.
RemoteServer Имя компонента соединения (например, DCOMConnection ), с помощью которого компонент подключается к удаленному модулю данных. Это свойство нужно настраивать в первую очередь.

Теперь рассмотрим основные методы компонента ClientDataSet.

Таблица 29.2. Важные методы компонента ClientDataSet
Метод Описание
AddIndex Создает локальный индекс. ClientDataSet не может эффективно управлять индексами на стороне сервера, однако он позволяет создавать локальные индексы, которые существенно облегчают работу с данными. Однако эти индексы невозможно сохранить вместе с набором данных, поэтому их нужно перестраивать при каждом открытии
ApplyRange Включает механизм фильтрации по созданному ранее диапазону.
ApplyUpdates Обновляет записи в базе данных. Имеет параметр - максимальное количество ошибок (по умолчанию 0), после которых обновление прекращается. Возвращает целое число - количество действительно допущенных ошибок.
Cancel Отменяет все неподтвержденные изменения записи.
CancelRange Отменяет механизм фильтрации по указанному диапазону.
CancelUpdates Отменяет все неподтвержденные изменения из пакета Delta, предназначенные для дальнейшей передачи на сервер.
DeleteIndex Удаляет локальный индекс.
EmptyDataSet Очищает буфер от всех записей.
Execute Выполняет SQL -запрос из свойства CommandText, меняя НД на стороне сервера.
FetchBlobs По умолчанию, большие BLOB -столбцы, которые могут содержать изображение, музыку или какие либо двоичные данные, в целях разгрузки трафика клиенту не передаются. Метод FetchBlobs явно запрашивает с сервера содержимое текущего BLOB -столбца.
FetchDetails Запрашивает с сервера недостающие данные из вложенных или подчиненных таблиц. Если свойство FetchOnDemand имеет значение True, то эти данные подгружаются автоматически, и применять метод не нужно.
FetchParams Получает с сервера приложений текущие параметры набора данных провайдера. Если параметров нет, метод не делает ничего.
GetNextPacket Запрашивает с сервера очередной пакет записей, который будет добавлен к свойству Data. Длина пакета в записях определяется свойством PacketRecords.
LoadFromFile Загружает данные из локального файла. Вместе с SaveToFile позволяет организовать отложенную обработку данных. Подробнее об этом поговорим ниже.
LoadFromStream Загружает данные из потока.
Post Подтверждает сделанные изменения в буфере. На сервере данные при этом не меняются, для этого нужно явно вызвать метод ApplyUpdates.
RefreshRecord Обновляет текущую запись, запрашивая ее с сервера.
RevertRecord Восстанавливает текущую запись, если она была изменена, но еще не сохранена на сервере.
SaveToFile Сохраняет данные в локальный файл. Отличается от аналогичного метода других компонентов наличием второго параметра - формата данных файла. Может быть три формата: dfBinary - двоичный формат, dfXML - формат XML и dfXMLUTF8 - формат XML в кодировке UTF8.
SaveToStream Сохраняет данные в поток.
< Лекция 28 || Лекция 29: 12
Евгений Медведев
Евгений Медведев

В лекции №2 вставляю модуль данных. При попытке заменить name на  fDM выдает ошибку: "The project already contains a form or module named fDM!". Что делать? 

Анна Зеленина
Анна Зеленина

При вводе типов успешно сохраняется только 1я строчка. При попытке ввести второй тип вылезает сообщение об ошибке "project mymenu.exe raised exception class EOleException with message 'Microsoft Драйвер ODBC Paradox В операции должен использоваться обновляемый запрос'. 

Денис Попов
Денис Попов
Россия, Оренбург, Оренбургский государственный университет, 2015
Рустам Кадыров
Рустам Кадыров
Россия, Тирлян, Тирлянская школа №5, 2003