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

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

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

  • Пользовательский ИД
  • Имя
  • Возраст

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

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

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

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


person Fabricio Araujo    schedule 19.04.2012    source источник
comment
не можете ли вы просто создать логическое поле internalcalc прямо в исходном наборе данных без всего этого беспорядка?   -  person vavan    schedule 20.04.2012
comment
После того, как я сделал этот компонент, жизнь стала проще, так как я могу создавать поля данных, которые CDS распознает как поля данных.   -  person Fabricio Araujo    schedule 24.04.2012
comment
но вы делаете много ненужной работы. и какой смысл создавать эти поля данных?   -  person vavan    schedule 25.04.2012
comment
Они значительно упрощают работу с настройками TDbGrid, чтобы получить нужную мне функциональность. Я также использую его, чтобы отметить, импортирована ли запись, и упорядочить ее на основе основной сущности результирующего набора (которая денормализована) ... И список продолжается ...   -  person Fabricio Araujo    schedule 25.04.2012
comment
Я считаю, что вы могли бы добиться того же, используя поля internalcalc и без копирования данных неэффективным способом   -  person vavan    schedule 26.04.2012


Ответы (4)


Похоже, что после загрузки данных из исходного набора данных вы можете вызвать _ 1_, чтобы добавить дополнительные поля:

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;

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

person Ondrej Kelle    schedule 01.05.2012
comment
Похоже, проблема была между стулом и клавиатурой. Блестящее решение. Принято и +1. - person Fabricio Araujo; 07.05.2012

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

  1. Создайте 2 объекта TClientDataset (источник и цель)
  2. В Origin загружаем данные, полученные из параметров метода InternalGetRecords
  3. В Target создайте fielddefs, определенные из набора данных Origin, и добавьте fielddefs, созданные разработчиком во время разработки.
  4. Target.CloneCursor(Origin); //there are more params than this, but this is the basic idea
  5. Target теперь будет содержать новое представление тех же данных, что и Origin, но с ограничениями по полям, фильтрам и т. Д., Существующим в Target. (Если вы не определили какие-либо поля, он скопирует поля Origin. Если вы определите поля, он будет соответствовать тому, что вы ему дали.)
  6. Скопируйте данные из Target, и это должно быть именно то, что вы ищете.
person Mason Wheeler    schedule 19.04.2012
comment
это не сработает, если OP действительно хочет иметь дополнительные поля fkData. если все, что ему нужно, это несколько полей поиска, вычислений, внутренних расчетов или агрегирования, нет необходимости возиться со всем этим копированием / клонированием, и это может быть достигнуто с помощью одиночных (исходных) компакт-дисков - person vavan; 20.04.2012
comment
Я попробовал эту идею, но она не сработала - все, что я получил, это массив данных от Origin. Может я что-то неправильно понял ... - person Fabricio Araujo; 25.04.2012

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

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

person Marco Cantù    schedule 27.04.2012
comment
Это должен быть комментарий, а не ответ. - person kobik; 29.04.2012
comment
Легендарный Марко Канто на мой скромный вопрос? Круто. Вернемся к работе: я создаю поля данных ПОСЛЕ cds.open (на InternalGetRecords в TDataSetProvider) - person Fabricio Araujo; 02.05.2012

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

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

person crefird    schedule 19.04.2012
comment
-1 Вроде не читали вопрос ... У Target CDS другие метаданные (с дополнительными полями). Так что, если я действительно просто скопирую вариант данных из источника в цель, у меня просто будет это - копия источника без требуемых дополнительных полей. - person Fabricio Araujo; 20.04.2012
comment
Когда я прочитал ваш вопрос, ваш набор данных Origin содержит «новые» поля, которые вы создали с помощью своего настраиваемого TDatasetProvider, а данные полей были получены из ваших переопределенных InternalGetRecords. Это основа моего ответа. В противном случае зачем вам настраиваемый TDatasetProvider? Вы можете создавать новые поля в Target, копируя информацию о поле из Origin. - person crefird; 20.04.2012
comment
Вы неправильно прочитали. У цели есть новые поля. Источник получает данные, полученные из параметров поставщика набора данных (чистые данные получают компоненты доступа к данным). - person Fabricio Araujo; 24.04.2012