RO39 – 在一个事务中实现多个ClientDataSets 更新

 RO39 – 在一个事务中实现多个ClientDataSets 更新

作者  Erick Sasse ( 葡萄牙语版本  www.ericksasse.com.br)
RemObjects 提示 : 我们相信本文是正确的 , 但我们不做任何保证 . 在此感谢 Erick Sasse 写的文章 , 很高兴在此发表 .
从两层迁移到三层第一个要面临的窍门就是摆脱在客户端控制事务 . 客户端不应该开始和提交事务 . 事实上客户端应该不知道任何事物 . 所有的事务逻辑应该放在服务端 .
本文向你展示如何在 RemObjects DataSnap 服务中创建一个方法 , 用以传递一个 ClientDataSet. Delta 集合并在单独的事务中向数据库中更新 , 以便于在更新时发生异常时回滚事务 .
这个方法只适用于你使用非嵌套 ( 主从关系 ) ClientDataSets  的情况 , 因为 DataSnap 默认情况下已经在单独事务中使用嵌套 ( 主从关系 ) 数据集 .
你现在需要一个 RO DataSnap server, 由于我不打算介绍如何创建这种服务 , 所以我们使用一个已经存在的服务 .
首先 , 你需要在服务端 RODL 中创建一下数据类型 . 使用 RO Service Builder, 创建一个 包含 ProviderName (string)   Delta (binary) 成员的 DeltaToApply 结构体 :
然后创建 DeltaToApply 类型的数组 :

接下来 , 在服务端创建接收这个数组的函数 . 我将这个函数添加到包含所有 Provider 的同一个服务中 , 因为我们要使用这个 Provider 更新数据 :
方法实现如下
procedure TNewService.ApplyUpdates(var ADeltaArray: DeltaArray);
var
 I: Integer;
 Provider: TDataSetProvider;
 ErrorCount: Integer;
begin
 // Put your code to start transaction
 try
    for I := to ADeltaArray.Count - do
    begin
      Provider := FindProvider(ADeltaArray[I].ProviderName);
      if not Assigned(Provider) then
        raise Exception.Create('Provider not found: ' + ADeltaArray[I].ProviderName);
 
      Provider.ApplyUpdates(VariantFromBinary(ADeltaArray[I].Delta), 0, ErrorCount);
      if ErrorCount > then
        // Put your code to handle errors
        raise Exception.Create('Errors during applyupdates: ' + Provider.Name);
    end;
    // Put your code to commit the transaction
 except
    // Put your code to rollback the transaction
    raise;
 end;
end;
我已经创建了一个帮助函数去根据名字获取一个 Provider:
function TNewService.FindProvider(ProviderName: string): TDataSetProvider;
var
 Component: TObject;
begin
 Component := FindComponent(ProviderName);
 if Component is TDataSetProvider then
    Result := Component as TDataSetProvider
 else
    Result := nil;
end;
服务端完成 . 在客户端 , 你需要创建一个方法将所有的 ClientDataSet.Delta 保存在数组并将其发送到服务端 :
procedure TClientForm.ApplyUpdates(ClientDataSets: array of TClientDataSet);
var
 Deltas: DeltaArray;
 Delta: DeltaToApply;
 I: Integer;
begin
 Deltas := DeltaArray.Create;
 try
    for I := Low(ClientDataSets) to High(ClientDataSets) do
    begin
      if ClientDataSets[I].ChangeCount = then
        Continue;
 
      Delta := Deltas.Add;
      Delta.ProviderName := ClientDataSets[I].ProviderName;
      Delta.Delta := BinaryFromVariant(ClientDataSets[I].Delta);
    end;
    CoNewService.Create(ROMessage, ROChannel).ApplyUpdates(Deltas);
 finally
    Deltas.Free;
 end;
end;
VariantFromBinary   BinaryFromVariant  方法在 uROBinaryHelpers 单元内 .
最后 , 你只需要在客户端调用这个方法传递所有的你需要在同一个事务中更新的 ClientDataSet:
ApplyUpdates([ClientDataSet1, ClientDataSet2, ClientDataSet3]);
好了 ! 我希望这能对你有帮助 . 如果你发现代码存在问题或有可以改进的地方请尽快通知我以便于修正 .
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值