简体   繁体   English

为什么 - 如何 - 处理后处理交易?

[英]Why — HOW — are transactions processed after disposal?

I'm trying to work with some ambient transaction scopes ( thanks, ), which I haven't really done before, and I'm seeing some ... odd behavior that I'm trying to understand. 我正在尝试使用一些环境事务范围( 谢谢, ),我以前没有真正做过,而且我看到了一些......我想要理解的奇怪行为。

I'm trying to enlist in the current transaction scope and do some work after it completes successfully. 我正在尝试登记当前的事务范围,并在成功完成后做一些工作。 My enlistment participant implements IDisposable due to some resources it holds. 我的征募参与者由于拥有一些资源而实施了IDisposable I've got a simple example that exhibits the strange behavior. 我有一个展示奇怪行为的简单例子。

For this class, 对于这堂课,

class WtfTransactionScope : IDisposable, IEnlistmentNotification
{
    public WtfTransactionScope()
    {
        if(Transaction.Current == null)
            return;
        Transaction.Current.EnlistVolatile(this, EnlistmentOptions.None);
    }
    void IEnlistmentNotification.Commit(Enlistment enlistment)
    {
        enlistment.Done();
        Console.WriteLine("Committed");
    }

    void IEnlistmentNotification.InDoubt(Enlistment enlistment)
    {
        enlistment.Done();
        Console.WriteLine("InDoubt");
    }

    void IEnlistmentNotification.Prepare(
        PreparingEnlistment preparingEnlistment)
    {
        Console.WriteLine("Prepare called");
        preparingEnlistment.Prepared();
        Console.WriteLine("Prepare completed");
    }

    void IEnlistmentNotification.Rollback(Enlistment enlistment)
    {
        enlistment.Done();
        Console.WriteLine("Rolled back");
    }

    public void Dispose()
    {
        Console.WriteLine("Disposed");
    }
}

when used as illustrated here 当按照这里说明使用时

using(var scope = new TransactionScope())
using(new WtfTransactionScope())
{
    scope.Complete();
}

the console output demonstrates the wtf-ness: 控制台输出演示了wtf-ness:

Disposed 弃置
Prepare called 准备打电话
Committed 承诺
Prepare completed 准备完成

wut. 武汉理工大学。

I'm getting disposed before the transaction completes. 我在交易完成之前就已经处理好了。 This... kind of negates the benefits of hanging with the transaction scope. 这种......否定了挂起交易范围的好处。 I was hoping that I'd be informed once the transaction completes successfully (or not) so I could do some work. 我希望一旦交易成功(或不成功),我就会得到通知,这样我就可以做一些工作了。 I was unfortunately assuming that this would happen after scope.Complete() and before I get disposed as we move out of the using scope. 不幸的是我假设这会发生在scope.Complete()并且在我移出using范围之前我被处理掉。 This apparently is not the case. 显然事实并非如此。

Of course, I could hack it. 当然,我可以破解它。 But I've got other issues which essentially prevent me from doing this. 但我有其他问题基本上阻止我这样做。 I'll have to scrap and do something else in this eventuality. 在这种情况下,我将不得不废弃并做其他事情。

Am I doing something wrong here? 我在这里做错了吗? Or is this expected behavior? 或者这是预期的行为? Can something be done differently to prevent this from happening?? 可以采取不同的措施来防止这种情况发生吗?

This is self-inflicted pain. 这是自己造成的痛苦。 You violate a very basic rule for IDisposable, an object should only ever be disposed when it is no longer in use anywhere else. 您违反了IDisposable的一个非常基本的规则,只有在其他任何地方不再使用时,才应该处置该对象。 It is in use when your using statement calls Dispose(), you handed a reference to your object in the WtfTransactionScope constructor. 当您的using语句调用Dispose()时,它正在使用,您在WtfTransactionScope构造函数中提交了对象的引用。 You cannot dispose it until it is done with it, that necessarily means you have to dispose it after the using statement for the TransactionScope completes and the transaction got committed/rolled-back. 在完成它之前你不能处置它,这必然意味着你必须在TransactionScope的using语句完成并且事务被提交/回滚之后处理它。

I'll let you fret about making it pretty, but an obvious way is: 我会让你担心它变得漂亮,但一个显而易见的方法是:

using(var wtf = new WtfTransactionScope())
using(var scope = new TransactionScope())
{
    wtf.Initialize();
    scope.Complete();
}

The Prepare completed is merely an unhelpful debug statement. Prepare completed只是一个无益的调试声明。 Just delete it. 只需删除它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM