От новичка до гуру: Курсы программирования на CyberDuff

Как клонировать структуру набора данных (TFDQuery) в Delphi 10?

Может ли кто-нибудь помочь мне клонировать TFDQuery во время выполнения? Я кодирую в Delphi Tokyo, у меня есть модуль данных с TFDQuery, в котором я определил все свойства полей с помощью редактора полей во время разработки, таким образом, мой DBGrid1, который указывает на этот модуль данных этого набора данных, имеет все столбцы правильно отформатированные ( отображать имена, ширину, формат, порядок). Во время выполнения мне нужно создать новые экземпляры TFDQuery, TDatamodule и связать эти новые объекты с Dbgrid1. Мне нужно, чтобы этот новый TFDQuery был идентичен существующему, определенному во время разработки, чтобы сохранить DBgrid1 с теми же отображаемыми именами, шириной отображения и форматами отображения, что и во время разработки! Я пробовал следующие подходы к копированию определений полей набора данных:

**1-й подход: назначение метода для TFDQuery (не сработало) **

type
  TFormDados = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    DBGrid1: TDBGrid;
    Edit2: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    vconnection : TFDConnection;
    vdataset    : TFDQuery;
    vdatasource : Tdatasource;

  public
    { Public declarations }
  end;

var
  FormDados: TFormDados;

implementation

{$R *.dfm}
Uses
      unitdata;

procedure TFormDados.Button1Click(Sender: TObject);
var
  i : integer;
begin
     vconnection := TFDConnection.Create(nil);
     vconnection.Assign(Dtmodule.FDConGrafico);

     vdataset := TFDQuery.Create(nil);
     vdataset.Connection  := vconnection;

     vdataset.Assign(Dtmodule.FDQueryDados);  // Runtime Error : Cannot assign a TFDQuery to a TFDQuery

2-й подход: назначить FieldDefs из существующего набора данных новому — не сработало!

 ...
 vdataset.FieldDefs.Assign(Dtmodule.FDQueryDados.FieldDefs);
 vdataset.sql         := Dtmodule.FDQueryDados.sql;
 vdataset.params      := Dtmodule.FDQueryDados.Params;
 vdataset.FieldDefs.Update;
 vdataset.CreateDataSet;
 vdatasource          := Tdatasource.create(nil);
 vdatasource.DataSet  := vdataset;

 dbgrid1.DataSource   := vdatasource;

 vdataset.close;
 vdataset.Params[0].Asinteger := strtoint(edit1.Text);
 vdataset.Params[1].Asinteger := strtoint(edit2.Text);

 vdataset.Open;

Хотя метод Assign был запущен, vdataset не получил определения полей существующего FDQquery . После открытия vdataset DBGrid1 не отображал последовательность столбцов, метки и форматы для исходного набора данных, ПОЧЕМУ?

3-й подход — копировать определения полей по одному — не работает

for i:=0 to Dtmodule.FDQueryDados.Fields.Count -1 do
 begin
       with vdataset.FieldDefs.AddFieldDef do
       begin
            Name        := Dtmodule.FDQueryDados.FieldDefs[i].Name;
            Datatype    := Dtmodule.FDQueryDados.FieldDefs[i].DataType;
            Displayname := Dtmodule.FDQueryDados.FieldDefs[i].Displayname;
            Fieldno     := Dtmodule.FDQueryDados.FieldDefs[i].FieldNo;
       end;
 end;

 vdataset.FieldDefs.Update;
 vdataset.CreateDataSet;

 vdatasource         := Tdatasource.create(nil);
 vdatasource.DataSet := vdataset;

 dbgrid1.DataSource := vdatasource;

 ...

Этот код приводит к тому же результату, что и второй подход, т. е. он запускается, но после открытия vdataset DBGrid1 не показывает последовательность столбцов, метки и форматы для исходного набора данных.

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

Спасибо всем заранее !

01.11.2017

  • Затем сохраните и восстановите столбцы сетки БД. 01.11.2017
  • Попробуйте CopyDataSet с [coStructure] 01.11.2017
  • @Jason, сетка БД теряет информацию о столбцах, когда вы переназначаете источник данных. Код подобный этому может помочь вам сохранить его. Определения полей базового набора данных — это только одна часть. 01.11.2017
  • @ Джейсон, спасибо! Я попробовал предложенную вами команду: vdataset.CopyDataSet(Dtmodule.FDQueryDados, [coStructure]), но она вызвала ошибку: [FireDAC][Phys][Ora]-306. Текст команды не должен быть пустым. 01.11.2017
  • @Vitoria, спасибо за ссылку на код. Я попробовал это, и это решило частично !! Я смог восстановить некоторые части определений столбцов из исходного Dbgrid1, такие как порядок и видимые видимые столбцы, однако отображаемое имя и форматы отображения не были восстановлены. Пожалуйста, помните, что я сделал определения в полях TFDQuery, и этот набор данных был связан с Tdatamodule, который связан с DBgrid. Я не определял столбцы DBgrid! Я ценю вашу помощь ! 01.11.2017
  • Во втором подходе просто используйте vdataset.FieldDefs := DtModule.FDQueryDados.FieldDefs вместо .Assign, и это должно сработать. 01.11.2017
  • Привет всем, спасибо за советы. К сожалению, НИ ОДИН из них не работал! Я заметил, что когда я запускаю запрос этого набора данных, созданного во время выполнения, он перекрывает все существующие определения, даже если я использовал предложенные команды: 1) vdataset.CopyDataSet, 2) vdataset.FieldDefs: = DtModule.FDQueryDados.FieldDefs, 3) сохранить и восстановить определения столбцов DBgrid. Есть ли способ скопировать существующие определения полей из набора данных времени разработки в новый набор данных, созданный во время выполнения? Я рассчитываю на вашу помощь!! Спасибо 01.11.2017
  • Я думаю, вы спрашиваете, можете ли вы копировать постоянные поля.. Мне нужно провести несколько тестов.. 01.11.2017
  • Привет, ребята ... есть ли у кого-нибудь другие рекомендации для решения этой проблемы? Любая помощь очень приветствуется! 03.11.2017

Ответы:


1

Когда вы используете редактор полей для запросов, вы создаете поля, а не FieldDef. Из того, что я могу сказать, FieldDefs синхронизируются с FieldsCollection, когда компонент создается (или, возможно, открывается не на 100%). Свойства Display* недоступны для объекта FieldDef — они существуют только для объекта Field. Когда вы копируете структуру, вам нужно перебирать поля. Метод, который мы используем, приведен ниже.

Обратите внимание, что цикл и созданные элементы являются «Полями», но мы используем временный объект FieldDef, чтобы упростить код. TFieldDef.CreatField служит методом фабрики классов для получения правильного типа поля, т.е. TIntegerField против TStringField. Также, если вы используете вычисляемые поля, вам нужно будет подключить событие OnCalcField. Этот метод этого не делает.

procedure CopyFieldStructure(Source: TDataSet; Target: TDataset);
{^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^}
var
  Field: TField;
  NewField: TField;
  FieldDef: TFieldDef;
begin
  Target.Fields.Clear;
  Target.FieldDefs.Clear;

  // Cannot perform the next operation on an opened dataset
  if Target.State <> dsInactive then
    Target.Close;

  for Field in Source.Fields do
  begin
    // We are going to setup the first part in a FieldDef
    // that will set us use the CreateField Call in order to
    // get the correct subclass of TField created.
    FieldDef := Target.FieldDefs.AddFieldDef;
    FieldDef.DataType := Field.DataType;
    FieldDef.Size := Field.Size;
    FieldDef.Name := Field.FieldName;

    NewField := FieldDef.CreateField(Target);
    NewField.Visible := Field.Visible;
    NewField.DisplayLabel := Field.DisplayLabel;
    NewField.DisplayWidth := Field.DisplayWidth;
    NewField.EditMask := Field.EditMask;
    NewField.Calculated := Field.Calculated;
  end;
end;

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

А вот еще одна запись в блоге, в которой используется аналогичный подход: Как клонировать структуру полей TField и TDataset

Также не ведитесь на метод TDataSet.CopyField. Справка создает впечатление, что она может скопировать структуру поля. Когда на самом деле он копирует текущие поля «значения» для любых совпадающих имен полей.

03.11.2017
  • +1, однако, если необходимо скопировать такое свойство, как TFloatField.DisplayFormat, NewField.Datatype следует проверить и привести к соответствующему виду, например. TFloatField(NewField).DisplayFormat := TFloatField(Field).DisplayFormat 06.11.2017
  • Новые материалы

    Представляем Narwhal Technologies (Nrwl)
    6 декабря 2016 г. Маунтин-Вью, Калифорния С тех пор, как Виктор Савкин и я (Джефф Кросс) присоединились к команде Angular в Google на заре Angular 1, Angular продемонстрировал феноменальный..

    Путь AWS  — «Изучение машинного обучения — 10 начинающих ИИ и машинного обучения на AWS».
    Универсальный ресурсный центр для изучения искусственного интеллекта и машинного обучения. НОЛЬ или ГЕРОЙ, начните свое путешествие здесь. Получите решения и пройдите обучение у экспертов AWS...

    5 простых концепций Python, ставших сложными
    #заранее извините 1) Переменные x = 4 y = 5 Переменная в Python — это символическое представление объекта. После присвоения некоторого объекта переменной Python мы приобретаем..

    «Освоение вероятности: изучение совместной, предельной, условной вероятности и теоремы Байеса —…
    Виды вероятности: Совместная вероятность Предельная вероятность Условная вероятность Диаграмма Венна в вероятностях: В “Set Theory” мы создаем диаграмму Венна...

    Основы Spring: Bean-компоненты, контейнер и внедрение зависимостей
    Как лего может помочь нашему пониманию Когда мы начинаем использовать Spring, нам бросают много терминов, и может быть трудно понять, что они все означают. Итак, мы разберем основы и будем..

    Отслеживание состояния с течением времени с дифференцированием снимков
    Время от времени что-то происходит и революционизирует часть моего рабочего процесса разработки. Что-то более забавное вместо типичного утомительного и утомительного процесса разработки. В..

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