Шрифт:
Компонент SffifibEventAlerterl: TSffifibEventAlerterlпредназначен для получения приложением событий InterBase Компонент ссылается на конкретное подключение к базе данных, т.е. на компонент типа TpFIBDatabase (рис 2.73)
Рис 2.73. Свойства SIBfibEventAlerterl
Установим свойство AutoRegister в False, чтобы собственноручно зарегистрировать нужные нам события, а в свойстве Events перечислим те события, которые нас интересуют (рис. 2.74).
Рис 2.74. Список зарегистрированных событий
Чтобы компонент SIBfibEventAlerterl "получал" события, мы должны зарегистрировать их после подключения к базе данных. Для этого напишем обработчик события OnConnect у компонента pFIBDatabasel:
procedure TForml.pFIBDatabaselConnect(Sender: TObject);
begin
if not SIBfibEventAlerterl.Registered then
SIBfibEventAlerterl.RegisterEvents;
end;
Соответственно перед закрытием подключения желательно "отключить" SIBfibEventAlerterl. Для этого создадим обработчик события BeforeDisconnect компонента pFIBDatabasel:
procedure TForml.pFIBDatabaselBeforeDisconnect(Sender:
TObject);
begin
if SIBfibEventAlerterl.Registered then
SIBfibEventAlerterl.UnRegisterEvents;
end;
Зададим свойство Tag у кнопок равным соответственно 1, 2 и 3, и напишем общий обработчик события OnClick для них:
procedure TForml.ButtonsClick(Sender: TObject);
begin
if not pFIBTransactionl.InTransaction then
pFIBTransactionl.StartTransaction;
pFIBStoredProcl.Params[0].Aslnteger := TButton(Sender).Tag;
try
pFIBStoredProcl.ExecProc;
pFIBTransactionl.Commit;
except
pFIBTransactionl.Rollback;
end;
end;
Смысл кода очевиден - мы задаем значение параметра процедуры, используя свойство Tag у кнопки, на которую нажал пользователь, выполняем процедуру при помощи метода ExecProc и либо подтверждаем транзакцию, либо отменяем ее в случае ошибки. Нам остается только написать обработчик события OnEventAlert компонента SIBfibEventAlerterl:
procedure TForml . SIBf ibEvent Alerter 1 Event Alert (Sender : TObject ;
EventName: String, EventCount: Integer);
begin
ShowMessage(EventName + ' : ' + IntToStr(EventCount));
end;
Параметр EventName возвращает название произошедшего события, a EventCount возвращает количество событий EventName. Значение параметра EventCount требует некоторых разъяснений. Итак, при работе с событиями важно помнить, что реально они вызываются только в случае подтверждения транзакции. Иными словами, если вы вызываете некоторое событие 'NEW_CUSTOMER' при вставке записей в таблицу, и вызываете Commit только после вставки 1000 записей, то обработчик OnEventAlert будет вызван только один раз, сразу после Commit, и значение параметра EventCount будет равно 1000. Очевидно, что событие произошло 1000 раз, но приложение получает нотификацию обо всех событиях только после подтверждения транзакции, в контексте которой они происходили.
Мы можем запустить наше приложение. При нажатии на любую из кнопок мы будем получать сообщение о произошедшем событии, причем, как уже было сказано, если наше приложение запущено несколько раз и даже на разных компьютерах, все копии приложения будут получать нотификацию о событиях.
"Низкоуровневая" работа с внутренним буфером TpFIBDataSet
TpFIBDataSet включает несколько специальных методов для работы с внутренним буфером, в котором хранятся записи. В общем-то, данные методы превращают TpFIBDataSet в аналог TClientDataSet, ориентированный на InterBase. Наиболее интересным примером использования данных методов будет, пожалуй, построение диалога выбора, состоящего из двух списков (рис. 2.75).
Рис 2.75. Использование локального кеша TpFIBDataSet для организации двойного списка выбора
В данном примере мы будем использовать базу данных EMPLOYEE.GDB, входящую в стандартную поставку InterBase и FIBPlus. Покажем запросы для SourceDS:
SelectSQL:
SELECT
CUS.CUST_NO,
CUS.CUSTOMER
FROM
CUSTOMER CUS
ORDER BY CUS.CUSTOMER
UpdateSQL:
UPDATE CUSTOMER SET
CUSTOMER = ?CUSTOMER
WHERE
CUST_NO = ?OLD_CUST_NO
InsertSQL:
INSERT INTO CUSTOMER(
CUST_NO,
CUSTOMER
)
VALUES(
?CUST_NO,
?CUSTOMER
)
DeleteSQL:
DELETE FROM CUSTOMER
WHERE
CUST_NO = ?OLD_CUST_NO
RefreshSQL:
SELECT
CUS.CUST_NO,
CUS.CUSTOMER
FROM
CUSTOMER CUS
WHERE
(
CUS.CUST_NO = ?OLD_CUST_NO
)
Те же самые запросы мы будем использовать в TargetDS, поскольку оба компонента должны обладать совместимой структурой полей. Откроем оба запроса сразу после создания формы: