我在学习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;
在客户端调用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;
设
某个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的状态的,所以也没有问题