【问题标题】:My ClientDataSet.ApplyUpdates is not posting to my MySQL Database table?我的 ClientDataSet.ApplyUpdates 没有发布到我的 MySQL 数据库表中?
【发布时间】:2019-05-23 18:48:08
【问题描述】:

我想知道为什么我的客户端数据集上发布的数据没有使用 ApplyUpdates 更新到 MySQL 数据库表。

我正在处理 2 个数据库。

  1. DB1.CustomerTable1:没有问题,主键位于“ListID”—>CDS.Append —>CDS.ApplyUpdates

  2. DB2.CustomerTable2:有问题,主键位于“Guid”—> CDS.Edit —> CDS.ApplyUpdates。

我在 DB2.CustomerTable2 上添加了带有“ListID”的主键,但仍然无法正常工作。

下面的代码,我正在使用。

procedure TfrmMain.spbExportClick(Sender: TObject);
var
  Guid , VarAccountId, VarListSasId, VarListDspId : Variant;
  Status : String;
begin
  with dm.dmForm do
  begin
    cdsCustomer2.first;
    while not cdsCustomer2.eof do
    begin

      //variable data for CDS.Customer1.AllFields
      Guid := cdsCustomer2.FieldByName ('Guid').AsString;
      VarAccountId := cdsCustomer2.FieldByName('ListID').AsString;
      VarListSasId := cdsCustomer2.FieldByName('FullName').AsString;
      VarListDspId := cdsCustomer2.FieldByName('Name').AsString;
      Status := 'Out';

      //posting to CDS.Customer1.AllFields
      cdsCustomer1.DisableControls;
      cdsCustomer1.Append;
      cdsCustomer1.FieldByName('GUID').AsString := Guid;
      cdsCustomer1.FieldByName('AccountId').AsString := VarAccountId;
      cdsCustomer1.FieldByName('ListSasID').AsString := VarListSasId;
      cdsCustomer1.FieldByName('ListDspID').AsString := VarListDspId;
      cdsCustomer1.FieldByName('Status').AsString := Status;
      cdsCustomer1.EnableControls;
      cdsCustomer1.Fields[1].ProviderFlags := [pfInKey];
      cdsCustomer1.Post;

      //posting Guid value back to CDS.Customer2
      if cdsCustomer2.locate('ListID', VarAccountId, [])  then
      begin
        cdsCustomer2.DisableControls;
        cdsCustomer2.Edit;
        cdsCustomer2.FieldByName('ExternalGUID').AsString := Guid;
        cdsCustomer2.EnableControls;
        cdsCustomer2.Fields[0].ProviderFlags := [pfInKey];
        cdsCustomer2.Post;
      end;

      cdsCustomer2.Next;
    end;

    //ApplyUpdates to mysql Customer1.Table and Customer2.Table
    cdsCustomer1.ApplyUpdates(-1);
    cdsCustomer2.ApplyUpdates(-1);

  end;
end;

我希望这些代码会像数据库 1 一样简单地发布到我的 MySQL 数据库 2。除了发布 DB2 的 cdsCustomer2 之外,一切都可以发布到两个 ClientDataSet。

如果我在这里遗漏了一些您可能需要的信息,请告诉我。

附: 顺便说一下,这是数据库结构: UniConnection -> MySQLUniProvider -> UniQuery -> DataSetProvider -> ClientDataSet -> DataSource -> DBGrid

【问题讨论】:

  • cdsCustomer2.locate 调用看起来是多余的,因为键值是从之前的当前记录中获取的。此外,DisableControls 调用之前的注释看起来与实际代码无关。
  • @UweRaabe 谢谢。为混乱道歉。

标签: mysql delphi


【解决方案1】:

诊断 ApplyUpdates 问题可能有点乏味,因为有时需要仔细研究多种可能性,直到找到适合您情况的可能性,所以我不能告诉您“就这样做……”并且它会解决你的问题。

但是,在您开始考虑可能性之前,您的代码存在一些需要修复的问题,否则您不太可能取得任何进展。

  • 您对 ApplyUpdates 的调用

    cdsCustomer1.ApplyUpdates(-1);
    cdsCustomer2.ApplyUpdates(-1);
    

改成

  var Count : Integer;
  [...]
  Count := cdsCustomer1.ApplyUpdates(0);
  Assert(Count = 0);
  Count := cdsCustomer2.ApplyUpdates(0);
  Assert(Count = 0);

关键是,将 -1 指定为 ApplyUpdates 的参数 与您想要的完全相反,即它允许任意数量的错误 在 ApplyUpdates 过程中生成。你想要的是它 停止任何错误,这是 0 会做的,所以你可以找出 ApplyUpdates 期间返回了什么错误。

还有

  • 当您重新更新 cdsCustomer2 时,您错误地调用了 cdsCustomer1.DisableControls 而不是 cdsCustumer2.DisableControls。就目前而言,这个错误将阻止 cdsCustomer1 之后的正确显示。

进行这些更改,编译并运行您的应用程序,也许是两者之一 Count := [...] 会给你一个异常消息,它标识 你的问题的原因。如果没有:

  • 检查在您的服务器上,两个表都定义了主键,并且 然后检查您的 CDS 的正确字段是否具有 pfInkey 提供程序 标志设置。如果检查成功,请尝试将它们设置为 pfInWhere。

  • 在VCL源文件Provider.Pas中,找到程序

过程 TSQLResolver.InternalDoUpdate(Tree: TUpdateTree; UpdateKind: TUpdateKind);

它的最后一行应该是

DoExecSQL(FSQL, FParams);

在其上放置一个断点,运行您的应用程序,当它在 BP 上停止时,评估 FSQL,看看它是否正确。如果是这样,请尝试从您用于处理服务器的任何 MySql 实用程序执行相同的 SQL。

【讨论】:

  • 像往常一样,感谢您非常详细的回复。我已将错误 cdsCustomer2.DisableControls 更正为 cdsCustomer1.DisableControls。另一方面,我能够弄清楚这个问题。我提到了我正在使用的 2 个数据库。在我的数据模块上,我只有一个数据库 TUniConnection,即用于 cdsCustomer1。我没有用于 cdsCustomer2 的其他数据库的 TUniConnection。
  • 但更令人惊讶的是,在没有数据库 TUniConnection 的情况下,我能够读取 cdsCustomer2 的表数据。除了在编辑级别,这是我的主要问题。创建单独的 TUniConnection 后,我能够将数据推送到 DB2.CustomerTable2。
  • 关于 ApplyUpdates,我只想知道这是否是我将使用的标准编码,或者仅在这种情况下。现在,我已将 2 个 ApplyUpdates 分开并在每个帖子之后立即附加?
  • 您是否在每个 .Post 之后调用 .ApplyUpdates 取决于您,具体取决于您的应用程序的数据完整性要求 - 推迟它们可能会带来风险,并且如果用户没有找到它们也会严重烦人如果无法应用更新,请立即退出。
  • 顺便说一句@MartynA,我已经改为0而不是-1。如果将它们分开后,我会有点困惑,我还会做这些吗 Count := cdsCustomer1.ApplyUpdates(0);断言(Count = 0);?
【解决方案2】:

向 DataSetProvider 的 OnUpdateError 添加引发异常 - 默认情况下,异常是静默的,我一直不太了解。所以像 Raise Exception (E.Message) 这样的东西 - 你可能会发现你正在尝试使一个必须为非 null 或类似的字段为空。

【讨论】:

    【解决方案3】:

    在重现此案例以隔离错误的确切来源之后。我意识到我还没有为其他数据库创建连接。因此,这种情况的解决方案是为每个数据库创建连接,以便与两个数据库进行无缝通信。

    为了进一步说明,这是我现在拥有的连接,到目前为止我在同步 2 个数据库时没有收到任何错误:

    Database1 —> TUniConnection1 —> MySQLUniProvider1 —> TUniQuery1 —> TDataSetProvider1 —> TClientDataSet1 —> TDataSource1 —> TDBGrid1

    Database2 —> TUniConnection2 —> MySQLUniProvider2 —> TUniQuery2 —> TDataSetProvider2 —> TClientDataSet2 —> TDataSource2 —> TDBGrid2

    我不确定是否有更好的方法可以在一个项目中同时管理多个数据库连接。但是,这对我有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-19
      • 1970-01-01
      • 2022-11-26
      • 1970-01-01
      • 1970-01-01
      • 2017-03-21
      • 1970-01-01
      • 2023-03-20
      相关资源
      最近更新 更多