Учебная работа. Реферат: Модель briefcase средствами MIDAS

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (5 оценок, среднее: 4,80 из 5)
Загрузка...
Контрольные рефераты

Учебная работа. Реферат: Модель briefcase средствами MIDAS

Модель briefcase средствами MIDAS

Миша Голованов


В прошедшем номере журнальчика я писал о реализации модели Briefcase при помощи ADO. В отличие от ADO, средства работы с отключенными наборами данных в MIDAS были реализованы с самой первой версии. Реализация модели Briefcase средствами MIDAS несколько проще, хотя и тут есть свои подводные камешки.

приложение MIDAS состоит из 2-ух частей: сервера приложений и узкого клиента. Сервер приложений «разговаривает» с сервером БД (либо иным источником данных), реализует бизнес-правила и предоставляет узкому клиенту данные по запросу. Функция узкого клиента – это отображение данных юзеру.

В качестве примера мы спроектируем обычной приложений и узкий клиент для работы с базой, описанной в предшествующей части статьи. Сервер приложений реализуем как модуль MTS/COM+. Никаких особенностей сотворения сервера приложений для модели briefcase нет, потому я не буду обрисовывать этот процесс в деталях. В IDE Delphi сделаем новейший проект приложения для MTS/COM+, выбрав пункт меню File/New/Other, и в показавшемся диалоге выберем пункт activeX Library с закладки ActiveX. Потом включим в проект новейший удаленный модуль данных (File/New/Other и пункт Transactional Datamodule с закладки Multitier).

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


Компонент
Свойство
соединение с БД

adsParams:TADODataSet
Connection
Conn

CommandText
CommandText
select * from Params

dspParams:TDataSetProvider
DataSet
adsParams

Таблица 1

Откомпилируйте проект сервера и установите полученную dll в новое MTS/COM+-приложение c именованием MIDAS_briefcase, при помощи пт меню Run/Install COM+ Object.

Узкий клиент представляет собой DeskTop-приложение. Для связи с сервером приложений клиент употребляет один из компонент типа Connection с закладки DataSnap (мы воспользуемся DCOMConnection) и особый DataSet – ClientDataSet.

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


Компонент
Свойство
Таблица 2

Наружный вид формы приложения узкого клиента приведен на рисунке 1.

Набросок 1

Получение данных с центрального сервера

Получение данных с сервера приложений аналогично приведенному в примере для ADO. Код приведен ниже.

procedure TForm1.act_RemoteConnectExecute(Sender: TObject);

begin

try

with cdsParams do try

Close;

RemoteServer:=DCOMConn;

FileName:=»;

Active:=true;

except on E:Exception do

MessageDlg(Format(‘Ошибкаподключенияксерверу: %s’, [E.Message]),

mtError, [mbOk], 0);

end;

finally

DCOMConn.Close;

end;




Все просто, но для подключения к серверу нужно не забывать сбрасывать имя файла кэша (свойство FileName) и закрывать соединение с сервером опосля получения данных.

Чтение и запись данных из локального кэша

Для чтения данных из локального кэша у ClientDataSet есть способ LoadFromFile:

procedure TForm1.act_ConnectLocalExecute(Sender: TObject);

begin

with cdsParams do

begin

RemoteServer:=nil;

FileName:=ExtractFilePath(Application.ExeName) + LocalFile;

LoadFromFile(FileName);

end;

end;




Для записи в локальный кэш – способ SaveToFile:

with cdsParams do

SaveToFile(ExtractFilePath(Application.ExeName) + LocalFile);




снова же никаких сюрпризов.

Сохранение данных на , отмена изготовленных конфигураций

Для сохранения данных на предназначен способ CilentDataSet-а ApplyUpdates. Параметр данного способа показывает макисимально допустимое количество ошибок при передаче данных на .

procedure TForm1.act_SaveToServerExecute(Sender: TObject);

begin

if cdsParams.Active and (cdsParams.ApplyUpdates(0) = 0) then

act_RemoteConnect.Execute;

end;




При появлении ошибки генерируется событие OnReconcileError. Обработка ошибки осуществляется при помощи обычного модуля обработчика ошибки, подключить этот модуль в проект можно, выбрав ReconcileErrorDialog на закладке Dialogs (File/New/Other). Обработчик OnReconcileError будет смотреться при всем этом последующим образом:

procedure TForm1.cdsParamsReconcileError(DataSet: TCustomClientDataSet;

E: EReconcileError; UpdateKind: TUpdateKind;

var Action: TReconcileAction);

begin

Action:=HandleReconcileError(DataSet, UpdateKind, E);

end;




Для отмены внесенных конфигураций ClientDataSet содержит способ CancelUpdates.

Чтение данных «порциями»

Обмен данных меж узким клиентом и сервером приложений происходит пакетами. Пакет содержит информацию о метаданных и/либо набор записей. Увлекательной возможностью MIDAS является передача данных «порциями». естественно, данная возможность реализуется только во время наличия соединения с центральным сервером. Включение данной способности осуществляется установкой характеристики FetchOnDemand ClientDataset-а в true. К огорчению, даже при всем этом запрос к серверу базы данных выбирает все записи сходу. О одном из методов устранения этого недостатка я и желаю поведать.

1-ое, что нужно создать, это поменять текст SQL-запроса, находящегося в свойстве CommandText компонента adsParams (напомню, что это ADODataSet), на последующий:


select Top 2 * from Params where ParamID > :ID

При всем этом записи будут выбираться порциями по 2. естественно, что в настоящих приложениях размер пакета будет больше этого числа. Конкретное число представляет собой соглашение меж затратами времени на передачу пакета по сети (чем больше размер пакета, тем выше задержки при его передаче) и задержками, возникающими от нередкого воззвания с запросами к серверу БД. (на практике размер такового пакета зависит от размера записи, но в среднем составляет от 30 до 250 строк. – прим.ред.)

Остается решить делему, как клиент будет передавать серверу идентификатор крайней считанной записи (ParamID). неувязка эта возникает поэтому, что приложений не сохраняет состояние меж вызовами клиентов. С одной стороны, это делает приложений наиболее масштабируемым, но с иной, просит доп кода на стороне клиента для хранения состояния.

Для передачи значения первичного ключа крайней прочитанной клиентом записи можно употреблять событие BeforeGetRecords. Данное событие определено для набора данных ClientDataSet на клиенте и компонента провайдера на сервере. Перед получением пакета с записями это событие поначалу генерируется на клиенте, а потом у провайдера на сервере приложений. Событие имеет параметр, передаваемый по ссылке OwnerData (типа OleVariant). Вот через этот параметр мы и будем передавать

procedure TForm1.cdsParamsBeforeGetRecords(Sender: TObject;

var OwnerData: OleVariant);

begin

if not cdsParams.FieldByName(‘ParamID’).IsNull then

OwnerData:=cdsParams.FieldByName(‘ParamID’).Value;

end;




Соответственно для провайдера на сервере приложений:

procedure TMIDAS_bc.dspParamsBeforeGetRecords(Sender: TObject;

var OwnerData: OleVariant);

begin

if not VarIsNull(OwnerData) and not VarIsClear(OwnerData) then

adsParams.Parameters.ParamValues[‘ID’]:=OwnerData;

end;




Чтоб инициировать подкачку, нужно обрабатывать очередное событие объекта ClientDataSet – OnScroll:

procedure TForm1.cdsParamsAfterScroll(DataSet: TDataSet);

begin

if cdsParams.Eof then

cdsParams.GetNextPacket;

end;




Вызов cdsParams.GetNextPacket; как раз и инициирует получение последующего пакета данных.

Как выяснилось, код способа GetNextPacket содержит ошибку, выражающуюся в отказе чтения последующего пакета опосля нескольких попыток чтения первого пакета. Соединено это с неверным значением переменной ProviderEOF в описанной чуть повыше ситуации.

function TCustomClientDataSet.GetNextPacket: Integer;

begin

CheckActive;

if ProviderEOF then Result := 0 else

begin

UpdateCursorPos;

if (FPacketRecords = 0) and FMasterLink.Active and

(FMasterLink.Fields.Count > 0) then CheckDetailRecords else

begin

AddDataPacket(DoGetRecords(FPacketRecords, Result, 0, », Unassigned),

Result <> FPacketRecords);

ProviderEOF := Result <> FPacketRecords;

end;

Resync([]);

end;

end;




Исправлено это было очевидным присвоением ProviderEOF значения false перед выполнением проверки if ProviderEOF then Result := 0 else ……

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

]]>