I'm trying to work with some ambient transaction scopes (thanks, entity-framework), 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. 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:
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. 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??