вторник, 17 января 2012 г.

Оптимальное копирование из Recordset в TStrings

При работе с ADO компонентами часто возникает необходимость копирования данных из Recordset в структуры, которые в дальнейшем используются в программе. Такими структурами могут быть объекты определенного класса, массивы записей, всякого рода списки и т.п.
О том как скопировать данные с наименьшими затратами я опишу далее.

Обертка для ADO компонент Delphi описывает класс TCustomADODataSet от которого наследуются TADODataSet, TADOTable, TADOQuery и TADOStoredProc. В данном классе есть ссылка на ADO интерфейс Recordset (набор данных).
Типичный способ загрузки данных из ADO компонент сводится к циклу:
while not Eof do
begin
  //обработка записи из набора данных
  Next;
end;
Данный цикл является причиной увеличения времени обработки.
Чтобы избавиться от такого цикла можно использовать функцию GetRows у интерфейса Recordset. Для примера покажу загрузку списка идентификаторов и названий в TStrings:
//функция копирования
function ADOIdNameToStrings(ds: TCustomADODataSet): TStrings;
//вспомогательные структуры
type
  TRec = record
    id: TVarData;
    Name: TVarData;
  end;
  TRecArray = array[0..0] of TRec;
  PRec = ^TRecArray;
var
  i: Integer;
  PlainData: Variant;
  vcData: PRec;
begin
  Result := TStringList.Create;
  TStringList(Result).Duplicates := dupAccept;
  PlainData := ds.Recordset.GetRows(Integer(adGetRowsRest), adBookmarkFirst, VarArrayOf([0, 1]));
  Result.BeginUpdate;
  Result.Capacity := VarArrayHighBound(PlainData, 2);//выделяем память под все записи
  vcData := VarArrayLock(PlainData);//получаем указатель на массив из пар Variant
  try
    for i := Result.Capacity downto 0 do
      with vcData^[i] do
        Result.AddObject(Name.VOleStr, TObject(id.VInteger));
    //TStringList(Result).Sorted := True;//при необходимости можно отсортировать
  finally
    VarArrayUnlock(PlainData);
    Result.EndUpdate;
  end;
end;

Комментариев нет:

Отправить комментарий