如何让TFDQuery识别何时将新字段添加到TFDMemTable,它通过TFDLocalSQL进行查询

时间:2017-03-27 06:47:14

标签: delphi firedac

在现有TFDMemTable中添加字段后,通过TFDLocalSQL查询该表的任何TFDQuery都无法识别新字段。

下面的代码说明了这一点:在代码中添加了单个字段的TFDMemTable和在该表上执行select的TFDQuery。 (假设TFDMemTable被添加到TFDLocalSQL的DataSets属性,TFDQuery指向TFDConnection)将字段添加到实时TFDMemTable的过程来自example project和使用Unprepare,这看起来不像在这种情况下工作,来自这个question

procedure TForm2.FormCreate(Sender: TObject);
begin

  with FDMemTable1.FieldDefs.AddFieldDef do begin
    Name := 'col1';
    DataType := ftString;
    Size := 10;
  end;
  FDMemTable1.CreateDataSet;
  FDMemTable1.Active := true;

  FDQuery1.SQL.Text := 'SELECT * FROM FDMemTable1';

  FDConnection1.Connected := true;
  FDLocalSQL1.Active := true;
  FDQuery1.Active := true;
end;

procedure TForm2.Button1Click(Sender: TObject);
var
  tempMT: TFDMemTable;
begin
  tempMT := TFDMemTable.Create(nil);

  try
    tempMT.Data := FDMemTable1.Data;
    FDMemTable1.Close;
    with FDMemTable1.FieldDefs.AddFieldDef do begin
      Name := 'col99';
      DataType := ftString;
      Size := 10;
    end;
    FDMemTable1.Open;
    FDMemTable1.MergeDataSet(tempMT, dmDataSet, mmNone);
    if not FDMemTable1.FieldDefs.Updated then FDMemTable1.FieldDefs.Update;
  finally
    tempMT.Free;

    FDQuery1.Active := false;
    FDQuery1.Unprepare;              // this is meant to uncache the fields
    FDQuery1.Active := true;         // Does not include 'col99' in result set
  end;
end;

该字段肯定已添加到TFDMemTable并且工作正常。关于如何让TFDQuery识别新列的任何提示。

1 个答案:

答案 0 :(得分:1)

我认为您获得此行为的原因是您的代码缺少一步。

在点击处理程序的finally子句中,您需要关闭FDConnection,就像这样

  finally
    tempMT.Free;

    FDConnection1.Connected := False;
    FDQuery1.Active := false;
    FDQuery1.Unprepare;              // this is meant to uncache the fields
    FDQuery1.Active := true;         // Does include 'col99' in result set
    Caption := IntToStr(FDQuery1.FieldCount);
  end;
  PageControl1.ActivePage := TabSheet3;  // has FDQuery grid

完成上述更改后,您会发现在FDQuery1中获得了添加的列。顺便说一句,你可以拿出FDQuery.Unprepare,因为它没有任何区别。 Prepare通常用于编译后端数据库服务器内的查询的SQL代码。在这种情况下,不涉及后端服务器,因为FDLocalSQL1组件从mem表生成FDQuery1的数据。 Unprepare通常告诉后端服务器它可以释放已编译的查询资源。

我认为你的版本不起作用的原因是因为调用了

中的GetActualActive
procedure TFDCustomLocalSQL.CheckActivate;
var
  i: Integer;
begin
  if GetActualActive and not FActivated then begin
    for i := 0 to DataSets.Count - 1 do
      DataSets.CheckUnique(DataSets[i]);
    FActivated := True;
    InternalAttachToSQL;
    for i := 0 to DataSets.Count - 1 do
      if DataSets[i].IsValid then
        InternalDataSetAdded(DataSets[i]);
  end;
end;

GetActualActive定义为

function TFDCustomLocalSQL.GetActualActive: Boolean;
begin
  Result := Active and (Connection <> nil) and Connection.Connected;
end;

因此,如果FDLocalSQL1之前处于活动状态,那么CheckActivate的其余部分将被跳过,而且FDConnection已经连接了。因此,断开FDConnection允许CheckActivate的内部执行,因此FDLocalSQL1“注意到”对FDMemTable1结构的更改。

顺便说一句,而不是从头开始编写代码,我将我的项目基于这个:

D:\ D10 \ Samples \ Object Pascal \ Database \ FireDAC \ Samples \ Comp Layer \ TFDLocalSQL \ InMemDB

避免了对项目设置方式的一定程度的猜测。