Более быстрый способ перемещения данных из структуры набора данных в другую (в TDatasetProvider)
У меня есть пользовательский TDatasetProvider, который позволяет создавать новые поля для любых данных, которые он предоставляет.
Итак, предположим, вы получили следующие поля в исходном наборе данных:
- CustomerId
- имя
- возраст
и вам нужно выбрать его на DBGrid, используя отображение растрового изображения. Ну, вы можете, так как мой DSP может добавить
логическое поле с именем Selected
в набор данных.
то, как я это делаю теперь:
- создайте 2 объекта TClientDataset (Origin и Target)
- в Origin я загружаю данные, полученные из параметров метода InternalGetRecords (я его переопределил)
- в Target я создаю fielddefs, определенные Из исходного набора данных, и добавляю fielddefs, созданные во время разработки разработчиком
- выполнить CreateDataset на целевой
- и, строка за строкой (и поле за полем), я копирую данные из исходной базы данных в Целевой набор данных
- в конце концов, верните вариант данных в качестве возвращаемого значения из 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-->
- создайте 2 объекта TClientDataset (Origin и Target)
- в Origin загрузите данные, полученные из параметров метода InternalGetRecords
- в Target создайте fielddefs, определенные Из исходного набора данных, и добавьте fielddefs, созданные во время разработки разработчиком
Target.CloneCursor(Origin); //there are more params than this, but this is the basic idea
- Target теперь будет содержать новое представление тех же данных, что и Origin, но ограничены какими-либо полями, фильтрами и т. д. существуют на цели. (Если вы не определили какие-либо поля, он будет копировать поля Origin. Если вы определяете поля, то он придерживается того, что вы ему дали.)
- копировать данные из Target, и это должно быть именно то, что вы ищете.
У меня есть образец, который добавляет поля в компакт-диски динамически, используя анонимные методы для вычисления отдельных полей, чтобы достичь большей гибкости. Перед открытием компакт-дисков вы добавляете вычисляемые поля, а затем открываете их..
Это то, что вы ищете? Вопрос не очень ясен...
вы можете использовать свойство Data TClientDataset для копирования всего набора данных, метаданных и данных. Предполагается, что это самый быстрый способ скопировать один TClientDataset в другой.
см.http://docwiki.embarcadero.com/RADStudio/en/Assigning_Data_Directly