无法访问已处置的对象。交易

时间:2009-08-25 10:46:34

标签: c# entity-framework transactions transactionscope

我们正在使用Entity Framework并在事务范围内运行单元测试。我们原来在标题中得到了错误。

我设法将问题与某些问题隔离开来。

using (TransactionScope scope1 = new TransactionScope())
{
    using (TransactionScope scope2 = new TransactionScope())
    {
           // Here there is no code
    }

    using (Entities se = new Entities())
    {
        EntityConnection entityConnection = (EntityConnection)se.Connection;
        DbConnection storeConnection = entityConnection.StoreConnection;

        storeConnection.Open(); // On this line the error occurs

           // Some code that runs a stored procedure
    }
}

我们当前得到的错误是“操作对交易状态无效......”

如果删除事务范围2,一切正常。

如果我将范围2标记为环境事务,它也可以正常工作。

2 个答案:

答案 0 :(得分:9)

您创建的scope2没有明确的TransactionScopeOption参数,默认值为TransactionScopeOption.Required,请参阅TransactionScope Constructor

中的备注部分
  

此构造函数创建一个新的   事务范围与事务   范围选项等于必需。这个   意味着需要交易   由新的范围和环境   如果已经使用了交易   存在。否则,它会创建一个新的   进入范围之前的交易。

在您的示例中,环境TransactionScope确实已存在(scope1),因此具有隐式参数TransactionScope的新嵌套scope2TransactionScopeOption.Required)是使用现有的环境事务而不是自己创建新事务。

但是,scope2的隐式事务语义仍然存在,因此scope1创建的现有环境事务将中止,因为您未在scope2结束时调用Complete {1}}:

  

未能调用此方法会中止   交易,因为交易   经理将此解释为一个系统   失败,或等同于例外   抛出交易范围

当然,如果您删除scope2或将其语义更改为TransactionScopeOption.RequiresNew(意味着'始终为范围创建新事务。'),问题会立即消失。 ,因为scope1创建的现有环境事务不再受影响。

有关详细信息,请参阅Implementing an Implicit Transaction using Transaction Scope

答案 1 :(得分:0)

这种语法怎么样,这非常相似,Scope2已经完成并稍后处理。

我也间歇地看到“无法访问已处置的对象'交易'错误。 可能是因为我应该使用TransactionScopeOption.RequiresNew而不是TransactionScopeOption.Required创建这两个?

 TransactionOptions rootOptions = new TransactionOptions();
    rootOptions.IsolationLevel = IsolationLevel.ReadCommitted;
    OtherObject.Scope2 = new TransactionScope(TransactionScopeOption.Required, rootOptions);

    TransactionOptions options = new TransactionOptions();
    options.IsolationLevel = IsolationLevel.ReadCommitted;
    options.Timeout = getTransactionTimeout();
    using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, options))
                {

                                .............
                    scope.Complete();
                }