0

What happens when an transaction is started in a using then an exception happens but an rollback never occurs, because there is no try - catch rollback?

To illustrate the question more in detail see the following example: We use the unit of work pattern to generate the business transactions.

The unit of work is encapsulated in a using. When starting the unit of work we might start a transaction (see example below.)

//Starts a transaction
using (var uow = repositoryFactory.BeginUnitOfWork(true))
{
    //do stuff
    uow.Commit();
}

The transaction is started using the entity framework:

 CurrentContext.Database.BeginTransaction()

The question is now, what happens when an exception is thrown while "do stuff" the rollback is automatically triggered?

The repository factory Disposes the "CurrentContext" as follow:

public void Dispose()
{
    if (CurrentContext != null)
    {
        CurrentContext.Dispose();
    }
    CurrentContext = null;
    GC.SuppressFinalize(this);
}

What I have found was, that an open transaction will be closed if the connection to the database is closed (s. What happens if you don't commit transaction in a database (say SQL Server)). The problem with that is, that when a connection is closed it's release back into the pool (s. https://msdn.microsoft.com/en-us/library/8xx3tyca(v=vs.110).aspx):

When a connection is closed, it is released back into the pool and into the appropriate subdivision based on its transaction context. Therefore, you can close the connection without generating an error, even though a distributed transaction is still pending. This allows you to commit or abort the distributed transaction later.

Community
  • 1
  • 1
suizo
  • 531
  • 8
  • 24

1 Answers1

0

There is no try-catch block, but there is try-finally block and that is the using statement itself, which is roughly equivalent to the following:

var uow = repositoryFactory.BeginUnitOfWork(true);
try
{
    //do stuff
    uow.Commit();
}
finally {
    // pseudo-code
    if (!uow.IsComplete) {
        uow.Rollback();
    }
}

So if exception happens - transaction will be rolled back, even without explicit try-catch block inside using. Same will happen if you do not commit it explicitly.

Evk
  • 98,527
  • 8
  • 141
  • 191
  • Hi, I'm not sure if that's completely right. Were do you take your assumption that your pseudo code will be called? There might be some time in between before the garbage collector collects all the objects and the Rollback is called. – suizo Nov 15 '16 at 10:51
  • @suizo not sure what exactly you mean. This is how using block works - it's basically just try-finally block. Finally block will call Transaction.Dispose in any case (exception is thrown or not). Transaction.Dispose will rollback transaction for you, if it was not comitted. – Evk Nov 15 '16 at 10:57