Более быстрый способ перемещения данных из структуры набора данных в другую (в TDatasetProvider)

У меня есть пользовательский TDatasetProvider, который позволяет создавать новые поля для любых данных, которые он предоставляет.

Итак, предположим, вы получили следующие поля в исходном наборе данных:

  • CustomerId
  • имя
  • возраст

и вам нужно выбрать его на DBGrid, используя отображение растрового изображения. Ну, вы можете, так как мой DSP может добавить логическое поле с именем Selected в набор данных.

то, как я это делаю теперь:

  1. создайте 2 объекта TClientDataset (Origin и Target)
  2. в Origin я загружаю данные, полученные из параметров метода InternalGetRecords (я его переопределил)
  3. в Target я создаю fielddefs, определенные Из исходного набора данных, и добавляю fielddefs, созданные во время разработки разработчиком
  4. выполнить CreateDataset на целевой
  5. и, строка за строкой (и поле за полем), я копирую данные из исходной базы данных в Целевой набор данных
  6. в конце концов, верните вариант данных в качестве возвращаемого значения из InternalGetRecords.

Я действительно не знаю, есть ли более элегантный (и быстрый) способ сделать это. Есть еще один (более быстрый и / или элегантный) способ получить этот результат?

4 ответов


Кажется, что после загрузки данных из исходного набора данных вы можете вызвать IDSBase.AddField чтобы добавить больше полей:

uses
  DB, DBCommon, DBClient, DSIntf;

type
  THackClientDataSet = class(TClientDataSet);

procedure EncodeFieldDesc(var FieldDesc: DSFLDDesc;
  const Name: string; DataType: TFieldType; Size, Precision: Integer;
  Calculated: Boolean; Attributes: TFieldAttributes);
begin
  // ... copied from TClientDataSet.EncodeFieldDesc
end;

//...
var
  FldDesc: DSFLDDesc;
begin
  FillChar(FldDesc, SizeOf(FldDesc), 0);
  EncodeFieldDesc(FldDesc, 'SELECTED', ftBoolean, 0, 0, False, []);
  with THackClientDataSet(DataSet) do
    Check(DSBase.AddField(@FldDesc));
  // now you can create a second client dataset and assign it DataSet.Data directly:
  // DataSet2.Data := DataSet.Data;
  // DataSet2 now contains the new field (with empty values in all existing records)
end;

Я не тестировал его тщательно, но простой пример выше работал, как ожидалось, я смог перемещаться по второму набору данных клиента и редактировать значения всех полей, как обычно.


самый быстрый способ-использовать CloneCursor. Что-то вроде этого:--3-->

  1. создайте 2 объекта TClientDataset (Origin и Target)
  2. в Origin загрузите данные, полученные из параметров метода InternalGetRecords
  3. в Target создайте fielddefs, определенные Из исходного набора данных, и добавьте fielddefs, созданные во время разработки разработчиком
  4. Target.CloneCursor(Origin); //there are more params than this, but this is the basic idea
  5. Target теперь будет содержать новое представление тех же данных, что и Origin, но ограничены какими-либо полями, фильтрами и т. д. существуют на цели. (Если вы не определили какие-либо поля, он будет копировать поля Origin. Если вы определяете поля, то он придерживается того, что вы ему дали.)
  6. копировать данные из Target, и это должно быть именно то, что вы ищете.

У меня есть образец, который добавляет поля в компакт-диски динамически, используя анонимные методы для вычисления отдельных полей, чтобы достичь большей гибкости. Перед открытием компакт-дисков вы добавляете вычисляемые поля, а затем открываете их..

Это то, что вы ищете? Вопрос не очень ясен...


вы можете использовать свойство Data TClientDataset для копирования всего набора данных, метаданных и данных. Предполагается, что это самый быстрый способ скопировать один TClientDataset в другой.

см.http://docwiki.embarcadero.com/RADStudio/en/Assigning_Data_Directly