【问题标题】:ApplyUpdates on REST with Firedac使用 Firedac 在 REST 上应用更新
【发布时间】:2015-07-01 13:44:14
【问题描述】:

我的项目使用带有 FireDac 的 REST 服务器。

我有一个通用函数,可以生成我的所有选择,但是当我尝试 ApplyUpdates 时,如果什么都不做。没有消息,没有崩溃,它只是继续运行,数据不会反映到数据库中。

我的代码:

function TServerMethods.ApplyUpdates(banco, tabela : String; const DeltaList: TFDJSONDeltas; var Mensagem : String) : Boolean; 
var 
  LApply : IFDJSONDeltasApplyUpdates; 
  Query : TFDQuery; 
begin 
  mensagem := ''; 
  result := false; 
  try 
    try 
      LApply := TFDJSONDeltasApplyUpdates.Create(DeltaList); 
      Query := CriaQuery(banco,Tabela); 
      Query.Open(); 
      LApply.ApplyUpdates(banco + '.' + tabela, Query.Command); 
      if LApply.Errors.Count > 0 then 
        raise Exception.Create(LApply.Errors.Strings.ToString); 
      result := true; 
    except 
      on E:Exception do 
      begin 
        mensagem := 'Ocorreu um Erro na atualização: ' + #13#10 + E.Message; 
      end; 
    end; 
  finally 

  end; 

end; 

GetDeltas 函数(生成 DeltaList 的函数):

function GetDeltas(Banco, Tabela : String; MemTable : TFDMemTable) : TFDJSONDeltas;
begin
  if MemTable.State in [dsInsert, dsEdit] then
    MemTable.Post;
  result := TFDJSONDeltas.Create;
  TFDJSONDeltasWriter.ListAdd(result, MemTable);
end;

我的“CriaQuery”功能:

function TServerMethods.CriaQuery(Database : String; Tabela : String = '') : TFDQuery;
var
  FieldName : Boolean;
  i : Integer;
begin
  result := TFDQuery.Create(self);
  result.Connection := Connection;
  result.FetchOptions.AutoFetchAll := afAll;
  result.name := 'Qry' + Database + tabela;
  result.SQL.Clear;
  FieldName := false;
  if Trim(Tabela) <> '' then
  begin
    result.SQL := MontaSQL(database + '.' + tabela);
    result.SQL.Add(' and 1 = 0');
    result.Open();
    QryCampos.First;
    result.IndexFieldNames := result.Fields[1].FieldName;
    for i := 0 to result.Fields.Count-1 do
    begin
      if (UPPERCASE(Copy(result.Fields[i].FieldName, Length(result.Fields[i].FieldName)-1,2)) = 'ID') and
         (not FieldName) then
      begin
        result.Fields[i].ProviderFlags := [pfInUpdate, pfInWhere, pfInKey];
        FieldName := true;
      end
      else
        result.Fields[i].ProviderFlags := [pfInUpdate];
    end;
    result.Close;
    result.SQL.Delete(result.SQL.Count-1);
  end;
end;

生成组件绑定的函数:

procedure LinkaComponente(Campo : TField; Dono : TFmxObject; Classe : String);
var
  BindSource : TBindSourceDB;
  BindingList : TBindingsList;
  Link : TLinkControlToField;
begin
  if Dono is TForm then
  begin
    BindSource := TBindSourceDB.Create(Dono);
  end
  else
  begin
    BindSource := TBindSourceDB.Create(Dono.Owner);
  end;
  BindingList := TBindingsList.Create(BindSource.Owner);
  Link := TLinkControlToField.Create(BindSource.Owner);
  BindSource.DataSet := Campo.DataSet;

  if Classe = 'TCheckBox' then
  begin
    Link.Control := Dono.FindComponent(Campo.FieldName);
    Link.CustomFormat := 'ToStr(%s) <> "N"';
    Link.CustomParse  := 'IfThen(%s,"S","N")';
  end
  else if Classe = 'TFrameF2' then
  begin
    Link.Control := (Dono.FindComponent('Frame' + Campo.FieldName) as TFrameF2).edtFK;
  end
  else
    Link.Control := Dono.FindComponent(Campo.FieldName);
  Link.DataSource := BindSource;
  Link.FieldName := Campo.FieldName;
  Link.Active := true;
end;

我调用 applyUpdates 函数的那一刻:

procedure TDMPadrao.DMApplyUpdates;
var
  Deltas : TFDJSONDeltas;
  Mensagem : String;
begin
  //repetir esses comando para todas as MemTables do DM na sua ordem de dependencia
  //       tabelas pai antes de tabelas filhas...
  try
    Deltas := GetDeltas(banco, tabela, FDMemTable);
  except
    on E:Exception do
    begin
      FDMemTable.Edit;
      MostraMensagemBasica('Ocorreu um Erro na atualização:' + #13#10 + E.Message);
      abort;
    end;
  end;
  if not DMClient.ServerMethodsClient.ApplyUpdates(banco, tabela, Deltas, Mensagem) then
  begin
    FDMemTable.Edit;
    MostraMensagemBasica(Mensagem);
    abort;
  end;
end;

阅读时一切正常。我只在调用 ApplyUpdates 函数时遇到问题

谢谢。

【问题讨论】:

  • 已知此功能可以按预期工作。必须与您的环境或代码有关。
  • 是的,我认为我的 GetDeltar 函数或创建查询的函数有问题。
  • 只是一个建议,在你的方法名中使用动词,比如“CriarQuery”。
  • Cesar 你介意把你的 CreateQuery 方法发给我吗?
  • @RicardoAlvaresPereiraJunior 它创建一个 TFDQuery 实例并链接 Connection 并设置 SQL 语句。默认自动生成的 SQL 是 'SELECT * FROM TableName',没有其他属性被更改。

标签: json rest delphi datasnap firedac


【解决方案1】:

我遇到了类似的问题,我解决了在 ApplyUpdates 之前将表名传递给 Query.UpdateOptions.UpdateTableName。

  • 你是在“CriaQuery”里面做的吗?
  • 您的 Delphi 版本是多少?

这是我的工作代码,我在 Delphi XE7 e XE7 Update 1 中对其进行了测试:

procedure TDBDM.ApplyDeltas(const ADeltaList: TFDJSONDeltas; const TableName: string);
var
  JSONDeltas: IFDJSONDeltasApplyUpdates;
  Query: TFDQuery;
begin
  JSONDeltas := TFDJSONDeltasApplyUpdates.Create(ADeltaList);
  Query := CreateQuery(TableName);
  try
    Query.UpdateOptions.UpdateTableName := TableName;
    JSONDeltas.ApplyUpdates(0, Query.Command);

    if JSONDeltas.Errors.Count > 0 then
    begin
      raise Exception.Create(JSONDeltas.Errors.Strings.Text);
    end;
  finally
    Query.Free;
  end;
end;

注意事项

  • 与您的代码不同,Query.Open 未被调用。
  • TFDMemTable.CachedUpdates 必须为 True

编辑:将客户端代码添加到 applyUpdates

我在 TFDMemTable.AfterPost 事件中调用此方法。

    const
      CustomerTableName = 'CUSTOMER';

    procedure TCustomersDataModuleClient.ApplyUpdates;
    var
      Deltas: TFDJSONDeltas;
    begin
      Deltas := TFDJSONDeltas.Create;
      TFDJSONDeltasWriter.ListAdd(Deltas, CustomerTableName, CustomersMemTable);
      RestClientModule.CustomersMethodsClient.ApplyUpdates(Deltas);
      CustomersMemTable.CommitUpdates;
    end;

【讨论】:

  • 我今天遇到了类似 urs 的问题,但它仍然没有更新数据库,query.open 行被添加和删除了很多次以进行测试。
  • 我只是复制了你的代码,没有改变任何东西,它没有更新,你介意给我生成你的 ADeltaList 的代码吗?
  • 哦,我用的是XE7。我相信问题出在 GetDeltas 或 CriaQuery 中
  • 知道了:我的 FDMemTable 中的 CachedUpdates 设置为 false
  • 伙计,我忘记了。如果 CachedUpdates 为 false,它将不起作用。也许我应该将它添加到我的答案中,以便人们可以使用这些信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-21
  • 1970-01-01
  • 2020-02-02
  • 1970-01-01
相关资源
最近更新 更多