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

发布于 2024-08-03 09:52:17 字数 681 浏览 8 评论 0原文

我们正在使用实体框架并在事务范围内运行单元测试。我们最初在标题中发现了错误。

我已经设法隔离了这个问题。

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 标记为环境事务,它也可以正常工作。

We are using Entity Framework and running unit tests within a transaction scope. We were origianally getting the error in the title.

I have managed to isolate the problem some what.

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

The error that we are currently getting is "The operation is not valid for the state of the transaction.."

If I remove transaction scope2, everything works fine.

If I mark scope 2 as an ambient transaction it also works fine.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

毁梦 2024-08-10 09:52:17

您正在创建没有显式 TransactionScopeOption 参数的scope2,这会产生默认值 TransactionScopeOption.Required,请参阅 TransactionScope 构造函数

这个构造函数创建一个新的
交易范围与交易
范围选项等于必需。这
表示需要进行交易
通过新的范围和环境
如果已经有交易,则使用交易
存在。否则,它会创建一个新的
进入范围之前进行交易。

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

但是,scope2 的隐式事务语义仍然存在,因此由 scope1 创建的现有环境事务将被中止,因为您没有调用 Completescope2 末尾:

调用此方法失败将中止
交易,因为交易
经理将此解释为一个系统
失败,或相当于异常
事务范围内抛出

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

有关详细信息,请参阅使用事务范围实现隐式事务

You are creating scope2 without an explicit TransactionScopeOption parameter, which yields a default of TransactionScopeOption.Required, see section Remarks within TransactionScope Constructor

This constructor creates a new
transaction scope with the transaction
scope option equal to Required. This
means that a transaction is required
by the new scope and the ambient
transaction is used if one already
exists. Otherwise, it creates a new
transaction before entering the scope.

In your example an ambient TransactionScope does indeed exist already (scope1), consequently the new nested TransactionScope (scope2) with implicit parameter TransactionScopeOption.Required is using the existing ambient transaction rather than creating a new transaction itself.

However, the implicit transaction semantics of scope2 are still in place, consequently the existing ambient transaction created by scope1 is getting aborted because you are not calling Complete at the end of scope2:

Failing to call this method aborts the
transaction, because the transaction
manager interprets this as a system
failure, or equivalent to an exception
thrown within the scope of transaction

Of course the problem goes aways immediately if you remove scope2 or change its semantics to TransactionScopeOption.RequiresNew (meaning 'A new transaction is always created for the scope.'), because the existing ambient transaction created by scope1 will not be affected anymore.

See Implementing an Implicit Transaction using Transaction Scope for more details on this.

梦行七里 2024-08-10 09:52:17

这个语法怎么样,这很相似,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();
                }

How about this syntax, this is pretty similar , Scope2 is Completed and Disposed of later.

I'm also intermittently seeing the "cannot access a disposed of object 'Transaction' error.
Could it be because I should have created both of these with TransactionScopeOption.RequiresNew instead of 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();
                }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文