有人可以帮我在运行时克隆TFDQuery吗?我在Delphi东京编码,我有一个带有TFDQuery的Datamodule,我在设计时使用Fields Editor定义了所有字段属性,这样我的DBGrid1指向这个数据集的Datamodule,所有列都正确格式化(显示名称,宽度,格式,顺序)。在运行期间,我需要创建TFDQuery,TDatamodule的新实例,并使用Dbgrid1链接这些新对象。我需要这个新的TFDQuery与设计时定义的现有TFDQuery相同,以保持DBgrid1具有相同的显示名称,显示宽度和显示格式作为设计时! 我尝试了以下方法来复制数据集字段定义:
**第一种方法: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
第二种方法:将现有数据集中的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没有显示源数据集的列序列,标签和格式。
感谢您帮助修复上述代码或实施正确的方法,将数据集字段定义从一个现有数据集复制到新数据集。
提前谢谢大家!
答案 0 :(得分:2)
当您使用字段编辑器进行查询时,您创建的字段不是FieldDefs。据我所知,FieldDef在创建组件时保持与FieldsCollection同步(或者可能无法100%确定地打开)。 Display *属性在FieldDef对象上不可用 - 它们仅存在于Field对象上。当你去复制结构时,你需要迭代字段。我们使用的方法如下。
请注意,循环和创建的项目是“Fields”,但我们使用临时的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问题。我认为这是我最初使用我的代码的地方:Is there some better way to copy all DataSet Fields and their properties to another DataSet?
以下是另一篇使用类似方法的博文:How to: Clone TField and TDataset fields structure
也不要被TDataSet.CopyField方法欺骗。帮助使它看起来像是可以复制字段结构。当它真正复制任何匹配字段名称的当前字段“值”时。