Мир InterBase

         

"Низкоуровневая" работа с внутренним буфером 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, поскольку оба компонента должны обладать совместимой структурой полей. Откроем оба запроса сразу после создания формы:

procedure TDualListForm.FormCreate(Sender: TObject); 
begin
SourceDS.Open;
TargetDS.CacheOpen; 
end;

Если мы не указываем в коде явного открытия базы данных, то это означает, что свойство Connected > компонета TpFlBDatabase было задано в True в design-time.

Обратите внимание на то, что TargetDS мы активируем при помощи специального метода CacheOpen. Этот метод не выполняет запрос из SelectSQL, а только подготавливает внутренний буфер компонента в зависимости от запроса в SelectSQL. Очевидно, что после запуска приложения мы увидим записи в левом списке и пустую таблицу в правом. Теперь мы можем написать процедуру, которая позволит переносить записи из одного списка в другой:

procedure TDualListForm.MoveRec(Select: Boolean); 
begin
if Select then begin
if (SourceDS.Active) and (not SourceDS.IsEmpty) then begin
TargetDS.CacheRefreshByArrMap(SourceDS, frklnsert, 
['CUST_NO'], ['CUST_NO']);
SourceDS.CacheDelete; 
end; 
end 
else begin
if (TargetDS.Active) and (not TargetDS.IsEmpty) then begin 
SourceDS.CacheRefresh(TargetDS, frklnsert, nil); 
TargetDS.CacheDelete; 
end; 
end; 
end;


Если параметр Select равен True, то мы будем переносить текущую запись из левого списка в правый, т. е. из SourceDS в TargetDS. Рассмотрим подробнее метод CacheRefreshByArrMap.

procedure CacheRefreshByArrMap(FromDataSet: TDataSet; Kind: 
TCachRefreshKind; const SourceFields, DestFields: array of 
String);

Метод позволяет вставлять или модифицировать текущую запись в локальный буфер компонента, т. е. без выполнения соответствующих модифицирующих запросов. Параметр FromDataSet указывает, из какого TpFIBDataSet мы хотим получить запись. Параметр Kind может принимать два значения: frkEdit или frklnsert. Frklnsert указывает, что мы хотим вставить новую запись, a frkEdit - что мы хотим изменить существующую. Параметр SourceFields описывает список полей из компонента источника, а список DestFields - список полей в TpFIBDataSet-приемнике. Формально названия полей в списках могут не совпадать, но необходимо, чтобы совпадали типы данных, иначе обмен данными будет невозможен. В нашем примере, как вы можете видеть, мы вставляем в TargetDS текущую запись из SourceDS. Данный метод использован здесь только для демонстрации, поскольку мы вполне могли бы обойтись методом CacheRefresh, который копирует соответствующие поля автоматически. После вставки записи необходимо удалить ее из компонента источника. Это делается при помощи метода CacheDelete, который также не выполняет соответствующий запрос (DeleteSQL), а удаляет запись только из локального буфера в памяти. Теперь, когда мы знаем, что делают процедуры CacheRefreshByArrMap, CacheRefresh и CacheDelete, код процедуры достаточно очевиден: мы копируем запись из компонента-источника в компонент-приемник и удаляем ее из компонента-источника.
То же самое можно сделать в цикле, если мы хотим перенести все записи сразу:

procedure TDualListForm.MoveAll(Select: Boolean);
var TmpDataSet: TpFIBDataSet;
begin
if Select then TmpDataSet := SourceDS else
TmpDataSet := TargetDS;
with TmpDataSet do begin 
try
DisableControls; 
First;
while not Eof do MoveRec(Select); 
finally
EnableControls;
end; 
end; 
end;



Остается написать обработчики события OnClick для кнопок:

procedure TDualListForm.ButtonlClick(Sender: TObject); 
begin
MoveRec(True); // SourceDS -> TargetDS 
end;
procedure TDualListForm.Button2Click(Sender: TObject); 
begin
MoveRec(False); // TargetDS -> SourceDS 
end;
procedure TDualListForm.Button3Click(Sender: TObnect); 
begin
MoveAll(True), // SourceDS -> TargetDS 
end;
procedure TDualListForm. Button4Click (Sender : TObject) ;
begin
MoveAll(False); // TargetDS -> SourceDS 
end;

Мы можем запустить наше приложение (рис 2.76)
Если мы будем нажимать на кнопку Button 1, то записи будут переноситься из левого списка в правый (рис. 2 77).
Все операции осуществляются только с данными внутри локальных буферов, не затражвают сервер и реальные данные в базе Наряду с описанными выше методами вы также можете использовать.

OpenAsCIone - открыть DataSet и скопировать данные из другого DataSet
CacheAppend - добавить запись в конец локального буфера.
SwapRecords - обменять записи в локальном буфере.
CacheEdit - задать значения полей у записи в локальном буфере.
Cachelnsert - вставить запись в локальный буфер
CacheModify - общий метод для вставки и изменения записи в локальным буфере
LoadFromFile - заполнить локальный буфер записями из файла.
LoadFromStream - заполнить локальный буфер записями из потока.
SaveToFile - сохранить локальный буфер в файл.
SaveToStream - сохранить локальный буфер в потоке

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



Рис 2.76. Внешний вид запущенного приложения



Рис 2.77. Внешний вид приложения при выборе пользователем трех записей


Содержание раздела