c# - TransactionScope 包装 ORM 调用,第二次调用时出现 TransactionStateAborted.CreateAbortingClone 异常

标签 c# tsql orm transactions

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

using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, _maxTimeout))
{
    ORM.DeleteItem();
    ORM.CheckIntegrity();
    scope.Complete();
}

这是一个手动操作的 ORM,这两个调用最终都在底部的嵌套事务范围内发挥作用。换句话说,当你向下挖掘时,DeleteItem() 有 使用 (TransactionScope newScope = new TransactionScope(TransactionScopeOptions.Required, _maxTimeout) {...}

和CheckIntegrity()也有相同之处。

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

但是当我们深入到 CheckIntegrity() 调用中的嵌套范围创建时,它会从 CreateAbortingClone 构造函数中抛出“事务中止错误”。内部异常为空。

大多数其他提到的 CreateAbortingClone 交互都与 DTC 提升(或其失败)有关,内部异常反射(reflect)了这一点。

我推断 CheckIntegrity() 调用中的中止异常是由于 DeleteItem() 引发了异常 - 即使它被吞没了。

A) 这是一个正确的推论吗? TransactionScope 是否对任何抛出、处理或不处理的异常敏感?

B) 在调用 CheckIntegrity() 之前有什么方法可以检测到这一点吗?我的意思是除了重新做我们的 ORM 让异常渗透或添加一些其他全局标志之外?

谢谢 标记

最佳答案

我只知道这是如何与 EF( Entity Framework )一起工作的

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

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


    }
}

然后事务链接到上下文。我不太了解您的代码如何建立这种联系,但可能是一些奇特的内置内容。

那么最好将其包装在 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);
}

所以最终代码看起来像

 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);
         }

    }
}

关于c# - TransactionScope 包装 ORM 调用,第二次调用时出现 TransactionStateAborted.CreateAbortingClone 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17552082/

相关文章:

c# - "Padding is invalid and cannot be removed"使用 AesManaged

tsql - 存储过程是否可以在 “IN”子句中​​使用动态参数?

php - 存储 JSON 响应的最佳方式?

java - JPA + 如何使用第三个表作为一对多关系中的联接来选择记录?

orm - 为什么使用数据库迁移而不是版本控制模式

c# - 填充 : SelectCommand. 连接属性尚未初始化。该怎么办?

c# - 使用 C# 将方法作为参数传递

c# - 为什么我在 Linq Query() 中没有得到 .CopyToDataTable()

sql - 如何在 SQL Server 中使用 group count()

sql-server - 从 T-SQL 构建 AST