Подтвердить что ты не робот

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

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

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

  • CustomerId
  • Имя
  • Возраст

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

Как я это делаю сейчас:

  • Создайте 2 объекта TClientDataset (Origin and Target)
  • В Origin я загружаю данные, полученные из параметров метода InternalGetRecords (я переопределял его)
  • В Target я создаю fielddefs, определенные из набора данных Origin, и добавляю разработчики файлы fielddefs, созданные во время разработки
  • Выполнить CreateDataset для цели
  • И, строка-by-row (и поле за полем), я копирую данные из базы данных Origin в набор данных Target
  • В конце верните вариант данных в качестве возвращаемого значения из InternalGetRecords.

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

4b9b3361

Ответ 1

Похоже, что после загрузки данных из исходного набора данных вы можете вызвать 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;

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

Ответ 2

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

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

Ответ 3

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

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

Ответ 4

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

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