我想知道为什么我的clientdataset上发布的数据没有使用ApplyUpdates更新到MySQL数据库表。
我正在研究2个数据库。
DB1.CustomerTable1:没问题,主键位于'ListID'-> CDS.Append-> CDS.ApplyUpdates
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 database2中。除了发布DB2的cdsCustomer2之外,所有工作都可以发布到两个ClientDataSets中。
让我知道我是否在这里错过了您可能需要的一些信息。
P.S。 顺便说一下,这是数据库结构: UniConnection-> MySQLUniProvider-> UniQuery-> DataSetProvider-> ClientDataSet-> DataSource-> DBGrid
答案 0 :(得分: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期间返回什么错误。
也
进行这些更改,编译并运行您的应用,也许是两者之一
Count := [...]
将为您提供一个异常消息,该消息标识了
问题的原因。如果没有:
检查服务器上是否两个表都定义了主键,并且
然后检查CDS的正确字段中是否包含pfInkey
提供程序
标志集。如果可以,请尝试将它们设置为pfInWhere。
在VCL源文件Provider.Pas中,找到过程
过程TSQLResolver.InternalDoUpdate(Tree:TUpdateTree; UpdateKind:TUpdateKind);
它的最后一行应该是
DoExecSQL(FSQL, FParams);
在其上放置一个断点,运行您的应用,当它在BP上停止时,评估 FSQL,看看它是否正确。如果是这样,请尝试使用与服务器一起使用的任何MySql实用工具执行相同的SQL。
答案 1 :(得分:0)
向DataSetProvider的OnUpdateError添加一个引发异常-默认情况下,异常是静默的,这是我从未完全理解的。所以像Raise Exception(E.Message)之类的东西-您可能会发现您正在尝试使必须为非null或类似值的字段为空。
答案 2 :(得分:0)
在重现这种情况后,可以隔离出错误的确切来源。我意识到我还没有为其他数据库创建连接。因此,针对这种情况的解决方案是为每个数据库创建连接,以便与2个数据库无缝通信。
为进一步说明,这是我现在拥有的连接,到目前为止,在同步2个数据库时没有任何错误:
数据库1 —> TUniConnection1 —> MySQLUniProvider1 —> TUniQuery1 —> TDataSetProvider1 —> TClientDataSet1 —> TDataSource1 —> TDBGrid1
数据库2 —> TUniConnection2 —> MySQLUniProvider2 —> TUniQuery2 —> TDataSetProvider2 —> TClientDataSet2 —> TDataSource2 —> TDBGrid2
我不确定在一个项目中是否有更好的方法可以同时管理多个数据库连接。但是,这对我有用。