В SQL-языке
InterBase определен операторPOST_EVENT "
Имя события";После его выполнения наступает событие с данными именем события. Сервер БД уведомляет о наступлении события все активные приложения, зарегистрировавшие свой интерес к данному событию посредством выполнения оператора
EVENT INIT. Эти операторы мы изучать не будем по той простой причине, что в клиентских приложениях, написанных на Delphi, они неявно выполняются компонентом TIBEventAlerter.Событие представляет собой уведомление о наступлении определенной ситуации и посылается сервером БД всем клиентским приложениям, которые зарегистрировались как получатели данного события.
Обмен событиями сервера и приложения часто очень важен и может широко использоваться. Например, пусть клиентское приложение должно обновлять НД после определенного количества изменений (например, 10 или 100), внесенных в таблицу БД одновременно работающими с ней пользователями. Тогда такое обновление может производиться приложением после получения 10(100) уведомлений от сервера о наступлении события изменения БД другими приложениями.
Может иметь место и обмен уведомлениями о наступлении каких-либо событий двумя одновременно работающими с одной и той же БД клиентскими приложениями, часто выполняющими по отношению к БД различные функции. В этом случае сервер БД выступает в качестве посредника. Так, например, может быть построена и почтовая система организации, где сервер БД выполняет функции рассылки сообщений, а одна из таблиц БД (или их группа) служит в качестве системы почтовых ящиков с различными правами доступа.
Delphi и компонент TIBEventAlerterКомпонент
TIBEventAlerter расположен в палитре компонентов на странице Samples. Тот факт, что он расположен не на страницах Data Contras или Data Access, можно объяснить специализацией компонента на работу с Borland InterBase.Для клиентских приложений, работающих с
Borland InterBase, этот компонент, во-первых, регистрирует на сервере приложение как приемник определенных событий, и во-вторых, позволяет эти события обрабатывать. В компоненте TIBEventAlerter определены следующие свойства, методы и события.property Database: TDatabase; -
содержит имя компонента TDatabase, управляющего соединением с БД, работающей под управлением Borland InterBase.property Events: TStrings; -
определяет список событий, о наступлении которых сервер БД будет информировать клиентское приложение.property Registered: Boolean; -
возвращает True, если программа зарегистрирована как приемник сообщений о наступлении событий, определяемых свойством Events.procedure RegisterEvents; - выполняет регистрацию приложения;
procedure UnregisterEvents; -
отключает регистрацию приложения как приемника сообщений. Данный метод не может применяться в обработчике события OnEventAlert. Перед выполнением метода в обработчике OnEventAlert полезно установить изменяемый параметр CancelAlerts в False. procedure OnEventAlert: TEventAlert; - обработчик события TEventAlert;TEventAlert = procedure( Sender: TObject; EventName: String;
EventCount: longint; var CancelAlerts: Boolean);
Назначение параметров:
• EventName -
содержит имя события, посланного сервером приложению клиента;EventCount -
содержит количество событий (типа, определенного параметром EventName), имевших место на сервере с момента последней передачи клиентскому приложению уведомления о наступлении событий;• CancelAlerts -
изменяемый параметр; значение True (по умолчанию) сообщает серверу о том, что клиентское приложение продолжает интересоваться событиями из списка, указанного в свойстве Events; False сообщает о том, что интерес приложения к уведомлению о событиях иссяк.34.3. Использование компонента
TIBEventAlerter для обработки событий сервера БД в клиентском приложенииПусть в БД, расположенной на сервере, для таблицы БД
RASHOD определены триггерыCREATE TRIGGER AIEVENT_RASHOD FOR RASHOD
ACTIVE
AFTER INSERT
AS
BEGIN
POST_EVENT "INS_POSTED";
END
CREATE TRIGGER AUEVENT_RASHOD FOR RASHOD
ACTIVE
AFTER UPDATE
AS
BEGIN
POST_EVENT "UPD_POSTED";
END
CREATE TRIGGER ADLEVENT_RASHOD FOR RASHOD
ACTIVE
AFTER DELETE
AS
BEGIN
-POST_EVENT "DEL_POSTED";
END
Для регистрации указанных сообщений в клиентском приложении разместим компонент TIBEventAlerter с именем
IBEventAlerterl. Укажем в его свойстве Database имя компонента TDatabase, управляющего соединением с удаленной БД. Установим свойство этого компонента Registered в True. В списке свойства Events определим события, при уведомлении о наступлении которых с сервера, в клиентском приложении должны предприниматься какие-либо действия (рис. 34.1). Определим обработчик события OnEventAlert. Пусть нам необходимо, чтобы через каждые десять изменений происходило обновление набора данных RashodQuery (компонент TQuery), ассоциированного с таблицей RASHOD. Это важно, поскольку клиентское приложение "не видит" изменений в БД. сделанных другими приложениями.procedure TFormI.IBEventAlerterlEventAlert(Sender: TObject;
EventName: string; EventCount: Longint; var CancelAlerts:
Boolean) ;
const GettingEventsCnt : Integer = 0;
STEP = 10;
Period : Integer = STEP;
begin
GettingEventsCnt := GettingEventsCnt + EventCount;
IF GettingEventsCnt > Period THEN begin
RashodQuery.Close;
RashodQuery.Open;
Period := GettingEventsCnt + STEP;
END;//if
34.4. Обмен сообщениями между приложениями
Пусть одновременно должны работать два клиентских приложения А и В, использующие одну и ту же удаленную БД. В процессе работы приложение В шлет сообщение приложению А, а то, в свою очередь, шлет приложению В подтверждение приема посланного сообщения.
Определим в удаленной БД следующие процедуры:CREATE PROCEDURE B_SEND_INIT
AS
BEGIN
POST_EVENT "B_LOADED";
END
CREATE PROCEDURE A_SEND_INIT
AS
BEGIN
POST_EVENT "A_LOADED";
END
В
форме приложения В разместим компоненты DatabaseB, IBEventAlerterB, StoredProcB (рис. 34.2).Компонент
DatabaseB управляет соединением приложения В с удаленной БД, общей для приложений А и В. Компонент StoredProcB предназначен для вызова хранимой процедуры B_SEND_INIT после нажатия кнопки "Послать сообщение к А":procedure TFormB.SendButtonClick(Sender: TObject);
begin
DataBaseB.StartTransaction;
StoredProcB.ExecProc;
DataBaseB.Commit;
end;
ЗАМЕЧАНИЕ.
Как можно заметить, вызов хранимой процедуры на сервере должен происходить в рамках подтвержденной транзакции:сервер рассылает зарегистрировавшимся для получения сообщений клиентам сообщение о наступлении события только после завершения транзакции, внутри которой возбуждается событие.
Компонент IBEventAlerterB отслеживает получение от сервера БД сообщения о наступлении события "A_LOADED". В этом случае просто визуализируется полученное сообщение в компоненте ListBoxB:
procedure TFormB.IBEventAlerterBEventAlert(Sender: TObject;
EventName: string; EventCount: Longint; var CancelAlerts:
Boolean) ;
begin
ListBoxB.Items.Add(EventName) ;
end;
В форме приложения А (рис. 34.3) размещены компоненты
DatabaseA, IBEvenlAlerterA, StoredProcA. Компонент DatabaseA управляет соединением приложения А с удаленной БД, общей для приложений А и В. Компонент StoredProcA предназначен для вызова хранимой процедуры A_SEND_INIT. Этот вызов происходит после получения компонентом IBEventAlerter А уведомления о наступлении события "B_LOADED":procedure TFormA.IBEventAlerterAEventAlert(Sender: TObject;
EventName: string; EventCount: Longint; var CancelAlerts:
Boolean);
begin
ListBoxA.Items.Add(EventName) ;
DataBaseA.StartTransaction;
StoredProcA.ExecProc;
DataBaseA.Commit;
end;
34.5. Обмен инициализирующими сообщениями между приложениями
Несколько усложним предыдущий пример. Пусть с удаленной БД одновременно работают приложения А и В, причем приложение А должно быть загружено в момент начала работы приложения В. Тогда приложение В должно проверить факт загрузки приложения А и, если оно не загружено, перейти в состояние ожидания. Работа приложением В может быть продолжена только после загрузки приложения А.
В этом случае приложение В должно претерпеть некоторые изменения. Отсылка сообщения к приложению А и ожидание поступления от него подтверждающего сообщения вынесена в отдельную форму
WailingForm. В ней размещены компоненты DatabaseB, StoredProcB, Timer 1 и IBEventAlerterB (рис. 34.4).Диалоговое окно "Ожидание ответа от приложения А"
Рис. 34.4. Форма
WailingFormКомпонент
DatabaseB управляет соединением приложения В с удаленной БД, общей для приложений А и В. Компонент StoredProcB предназначен для вызова хранимой процедуры B_SEND_INIT. Транзакция вызова хранимой процедуры осуществляется каждые 5 секунд компонентом Timer! (тип TTimer) в обработчике события On Timer:procedure TWaitingForm.TimerlTimer(Sender: TObject);
begin
DatabaseB.StartTransaction;
StoredProcB.ExecProc;
Databases.Commit;
end;
Повторяющийся вызов хранимой процедуры необходим, чтобы приложение А, если оно загружается позднее приложения В, наверняка получило от сервера уведомление о наступлении события "
B_LOADED". Как только компонент IBEvenlAlerierB получит от сервера обратное инициализирующее сообщение, посланное приложением А, компонент Timer} дезактивизируется и повторяющийся вызов хранимой процедуры B_SEND_INIT будет прекращен, программа сообщает серверу о том, что событие "A_LOADED" ее больше не интересует, а форма WailingForm закрывается:procedure TWaitingForm.IBEventAlerterBEventAlert(Sender: TObject;
EventName: string; EventCount: Longint; var CancelAlerts: Boolean);
begin
Timer1.Enabled := False;
FormB.ListBoxB.Items.Add(EventName) ;
CancelAlerts := True;
WaitingForm.ModalResult := mrOk;
end;
Перед вызовом из главной формы приложения В форма
WaitingForm динамически создается, а после окончания работы - уничтожается:procedure TFormB.FormActivate(Sender: TObject);
begin
WaitingForm := TWaitingForm.Create(Self);
WaitingForm.ShowModal;
WaitingForm.Free;
end;
В форме
WaitingForm отменены иконки выхода, минимизации и максимизации (свойство Border-Icons), чтобы предотвратить выход из формы до получения инициализирующего сообщения от приложения А.