Поиск по этому блогу

среда, 29 февраля 2012 г.

Справочники в списке

Компоненты:  TJvMemoryData (из JEDI), ADO
Работа со списками и объектами в них.
Для того, чтобы снять нагрузку с сервера баз данных и возложить ее на клиента, можно создать хранилище из кэшированных запросов. Пользователь не будет обращаться к базе всякий раз, когда ему придет в голову открыть справочник, вместо этого он поищет справочник сначала в кэше, а уж если там такового не оказалось, тогда он обратиться к базе.
Хранить запросы можно и на диске клиента, компонент TJvMemoryData позволяет без труда сохранять данные на диске и загружать их с диска. (реализация этой возможности достаточно тривиальна, я ее опустила). А этот код просто схематично демонстрирует работу подобного хранилища.
Схема:
Создаем объект
memSpr := TJvMemoryData.Create(nil);
Помещаем его в список
spr_list.AddObject(memSpr.Name, memSpr);
Достаем из списка
if spr_list[i]=spr_name + '_dst' then Result := TJvMemoryData(spr_list.Objects[i]);
 
Сам список создаем при создании модуля данных
procedure TdmExtData.DataModuleCreate(Sender: TObject);
begin
spr_list := TStringList.Create;
end;

Функция создает справочник и помещает его в хранилище
1. создаем справочник
2. копируем его во временную таблицу
3. помещаем временную таблицу с данными в список
входные параметры: 
spr_name- уникальное имя справочника
spr_stmt - текст SQL запроса для справочника
В качестве результата выполнения пусто или строка с сообщением об ошибке
function TdmExtData.CreateSpr(spr_name, spr_stmt: WideString): string;
var
dstExec: TADODataSet;
memSpr: TJvMemoryData;
dsSpr: TDataSource;
begin
// проверка соединения 
// прим. проверка есть такой спр-к в списке или нет  в отдельной процедуре
if conData.Connected = False then begin
Result:= 'Нет соединения';
Exit;
end;
dstExec := TADODataSet.Create(nil);
conData.BeginTrans;
try
dstExec.Connection := conData;
dstExec.CommandText := spr_stmt;
// открыть
try
dstExec.Open;
except on e:Exception do
Result:='Ошибка в запросе: ' + spr_stmt + ' ' + e.Message;
end;

if dstExec.Active then
begin
// создаем временную таблицу в которой и будем хранить нашу таблицу
memSpr := TJvMemoryData.Create(nil);
dsSpr := TDataSource.Create(nil);
memSpr.Name := spr_name + '_dst'; // имена должны быть уникальными
dsSpr.Name := spr_name + '_dts';
dsSpr.DataSet := memSpr;
dsSpr.AutoEdit:=False;
// заливаем данные
memSpr.CopyStructure(dstExec,false);
memSpr.LoadFromDataSet(dstExec, 0, lmAppend, true);
memSpr.Active:=True;
// теперь складываем в список-хранилище
// в списке одновременно будем хранить и dst (наборы) и их источники (datasource)
spr_list.AddObject(memSpr.Name, memSpr);
spr_list.AddObject(dsSpr.Name, dsSpr);
end;

finally
conData.CommitTrans;
FreeAndNil(dstExec);
end;
end;
 
Процедура  уничтожения списка (эту процедуру вешаем на событие Destroy модуля данных)
procedure TdmExtData.Destroy_spr_list;
var i: integer;
tmp: string;
begin
for I:=spr_list.Count - 1 downto 0 do
begin
tmp := spr_list[i];
if Pos('_dst',spr_list[i])>0 then TJvMemoryData(spr_list.Objects[i]).Free;
if Pos('_dts',spr_list[i])>0 then TDataSource(spr_list.Objects[i]).Free;
end; // i
spr_list.Free;
end;
 
Получить справочник по его имени, на выходе временная таблица
function TdmExtData.Get_DataSet_SPR(spr_name: WideString): TJvMemoryData;
var
i:Integer;
begin
Result := nil;
for i:=spr_list.Count-1 downto 0 do
begin
if spr_list[i]=spr_name + '_dst' then
begin
Result := TJvMemoryData(spr_list.Objects[i]);
Exit;
end;
end;
end;

Получить источник по имени набора
function TdmExtData.Get_DataSource_SPR(spr_name: WideString): TDataSource;
var
i:Integer;
begin
Result := nil;
for i:=spr_list.Count-1 downto 0 do
begin
if spr_list[i]=spr_name + '_dts' then
begin
Result := TDataSource(spr_list.Objects[i]);
Exit;
end;
end;
end;

Если такой таблицы в списке еще нет, то создать, если есть выдать источник
function TdmExtData.Get_or_Create_DataSource_SPR(
spr_name, spr_stmt: WideString): TDataSource;
begin
Result:= Get_DataSource_SPR(spr_name);
if Result=nil then
begin
CreateSpr(spr_name, spr_stmt);
Result:= Get_DataSource_SPR(spr_name);
end;
end;