无法访问已释放的对象。事务。

4
我们正在使用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个回答

9
您正在创建一个没有明确 TransactionScopeOption 参数的 scope2,这将产生默认值为 TransactionScopeOption.Required 的结果。请参阅 TransactionScope Constructor 中的 “Remarks” 部分。
这个构造函数创建了一个事务范围,其事务范围选项等于 Required。这意味着新范围需要一个事务,并且如果已经存在一个环境事务,则使用该事务。否则,在进入范围之前会创建一个新的事务。
在您的示例中,确实已经存在一个环境 TransactionScopescope1),因此具有隐式参数 TransactionScopeOption.Required 的新嵌套 TransactionScopescope2)正在使用现有的环境事务,而不是自己创建一个新的事务。
然而,scope2 的隐式事务语义仍然存在,因此由 scope1 创建的现有环境事务将被中止,因为您没有在 scope2 结束时调用 Complete
未调用此方法会中止事务,因为事务管理器将其解释为系统故障或相当于在事务范围内引发的异常。
当然,如果您删除 scope2 或将其语义更改为 TransactionScopeOption.RequiresNew(表示“始终为该范围创建新事务”),则问题立即消失,因为由 scope1 创建的现有环境事务不再受影响。
有关更多详细信息,请参见 使用事务范围实现隐式事务

1
谢谢,问题已解决,我忘记了加上scope2.complete()。 - Shiraz Bhaiji

0

这个语法怎么样,它非常相似,Scope2稍后会被完成和处理掉。

我也间歇性地看到“无法访问已处理的对象'Transaction'”错误。 这可能是因为我应该使用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();
                }

嗨,我也看到间歇性的“无法访问已释放的对象。对象名称:'TransactionScope'。你也修复了这个问题吗? - Tasio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接