TransactionScope在第二次调用时包装ORM调用,TransactionStateAborted.CreateAbortingClone异常

use*_*043 5 c# t-sql orm transactions

出于诊断原因,我们试图对我们的数据库状态进行一些完整性检查,因此我们将修改的ORM查询包含在TransactionScope中,再加上运行诊断的第二个查询 - 如下所示:

using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, _maxTimeout))
{
    ORM.DeleteItem();
    ORM.CheckIntegrity();
    scope.Complete();
}
Run Code Online (Sandbox Code Playgroud)

这是一个手动滚动的ORM,这两个调用最终都会在底层的嵌套事务范围内完成它们的操作.换句话说,当您向下挖掘时,DeleteItem()已经使用(TransactionScope newScope = new TransactionScope(TransactionScopeOptions.Required,_maxTimeout){...}

和CheckIntegrity()也有相同的.

在大多数情况下,它一直很好,但我遇到了奇怪的情况.当有人向查询输入一些错误的输入时,DeleteItem()调用可能会抛出异常.该异常在包装器下面的堆栈级别完全捕获并处理.我相信嵌套TransactionScope 之前也会抛出异常.

但是当我们在CheckIntegrity()调用中进行嵌套作用域创建时,它会从CreateAbortingClone构造函数中抛出"Transaction was aborted error".内部异常为null.

大多数其他提及CreateAbortingClone交互都与DTC促销(或其失败)有关,内部异常反映了这一点.

我推断CheckIntegrity()调用的中止异常是由于DeleteItem()抛出异常这一事实 - 即使它被吞噬了.

A)是正确的推论吗?TransactionScope对抛出,处理或不处理的任何异常都敏感吗?

B)有没有办法在进行CheckIntegrity()调用之前检测到它?我的意思是除了重新执行我们的ORM以使异常渗透或添加一些其他全局标志?

谢谢马克

Sea*_*kit 0

我只知道它如何与 EF(实体框架)一起使用

 using (var context = new MyContext(this._connectionString))
 {

    using (var dbContextTransaction = context.Database.BeginTransaction())
    {


    }
}
Run Code Online (Sandbox Code Playgroud)

然后事务被链接到上下文。我不熟悉你的代码如何建立这种联系,但可能是一些奇特的内置东西。

那么最好将其包装在 try/catch 中

try
{
   // do-stuff
   context.SaveChanges();
   //NB!!!!!!
   //----------------------
   dbContextTransaction.Commit();
}
catch (Exception ex)
{
    dbContextTransaction.Rollback();
    //log why it was rolled back
    Logger.Error("Error during transaction,transaction rollback", ex);
}
Run Code Online (Sandbox Code Playgroud)

所以最终的代码看起来像

 using (var context = new MyContext(this._connectionString))
 {

    using (var dbContextTransaction = context.Database.BeginTransaction())
    {
         try
         {
              // do-stuff //
              context.SaveChanges();
              ///////////////////////
              //if any exception happen, changes wont be saved unless Commit is called 
              //NB!!!!!!
              //----------------------
              dbContextTransaction.Commit();
         }
         catch (Exception ex)
         {
              dbContextTransaction.Rollback();
              //log why it was rolled back
              Logger.Error("Error during transaction,transaction rollback", ex);
         }

    }
}
Run Code Online (Sandbox Code Playgroud)