我在学习MIDAS,在学习过程中遇到一个问题,觉得TDataSetProvider的事务处理好象有点奇怪:
    在客户端调用ApplyUpdates以前,如果AppServer处于显式事务状态中,则Client调用
ApplyUpdates后,AppServer的DataSetProvider不会调用DataSet的PSEndTransaction,
也就是说发生错误,没有立即回滚,而即使不发生错误,也不会提交事务。
--如果是这样的话,是不是有问题呢?    我没有试过,我是看TDataSetProvider.InternalApplyUpdates的代码提这个问题的,
请各位给我解答这个疑惑,谢谢=========================================================================
注:我的DataSet组件是针对MsSqlServer的(不是Delphi提供的),
在PSInTransaction中的代码大致是:
begin
  InternalQuery.Close;
  InternalQuery.Sql.Text := 'select @@trancount as f0';
  InternalQuery.Open;
  Result := InternalQuery.Fields[0].AsInteger > 0;
  InternalQuery.Close;
end;
而PSStartTransaction的代码则会启动一个显式事务,
另外,我的Provider的设置是ResolveToDataSet为True.
=========================================================================
为方便各位讨论,转帖Delphi7中关于该过程的代码:
function TDataSetProvider.InternalApplyUpdates(const Delta: OleVariant;
   MaxErrors: Integer; out ErrorCount: Integer): OleVariant; override;
begin
  CheckDataSet;
  //如果此时我的DataSet.PSInTransaction返回True, 则fTransactionStarted = False
  fTransactionStarted := not IProviderSupport(DataSet).PSInTransaction;  //则不再启动事务
  if fTransactionStarted then
    IProviderSupport(DataSet).PSStartTransaction;
  try
    CheckResolver;
    Resolver.fUpdateTree.InitData(DataSet);
    try
      Result := inherited InternalApplyUpdates(Delta, MaxErrors, ErrorCount);
    finally
      Resolver.fUpdateTree.InitData(nil);
    end;
  finally
    //因为fTransactionStarted = False, 所以不Commit也不Rollback,是这样吗?
    if fTransactionStarted then
      IProviderSupport(DataSet).PSEndTransaction(
        (ErrorCount <= MaxErrors)
        or
        (MaxErrors = -1)
      );
  end;
end;

解决方案 »

  1.   

    摩托、ihihonline来啊,真的很困惑耶
      

  2.   

    昨天中午洗澡的时候想到一个解答,与大家分享,并希望大家多多洗澡:

      某个AppServer导出几个接口:
      function GetInTransaction: Boolean; stdcall;
      procedure StartTransaction; stdcall;
      procedure EndTransaction(aCommit: Integer); stdcall;主要的意图是希望能够自己控制事务,例如将几个ClientDataSet.ApplyUpdates组合在一个事务内:
       aRDM.StartTransaction;
       try
         ClientDataSet1.ApplyUpdates(0);
         ClientDataSet2.ApplyUpdates(1);
         ...
         aRDM.EndTransaction(Integer(True));
       except
         aRDM.EndTransaction(Integer(False));
       end;  那么
      if fTransactionStarted then
          IProviderSupport(DataSet).PSEndTransaction(
            (ErrorCount <= MaxErrors)
            or
            (MaxErrors = -1)
          );
    这一句在这种应用中就发挥它的作用了。而一般的应用中,通常服务器端执行伊始总是处于not InTransaction的状态的,所以也没有问题