Transaction rollback on dispose (SelfServicing)

Posts   
 
    
louthy
User
Posts: 61
Joined: 02-Aug-2005
# Posted on: 12-Nov-2007 00:19:21   

Does the Transaction object automatically rollback on dispose?

I notice plenty of code examples which do this:


Transaction transaction = new Transaction(...);

try
{
        // .. entity modify ...
        // .. entity save ...
        
        transaction.Commit();
}
catch(Exception e)
{
        transaction.Rollback();
        throw e;
}
finally
{
        transaction.Dispose();
}

I would prefer to use:


using( Transaction transaction = new Transaction(...) )
{
        // .. entity modify ...
        // .. entity save ...
        
        transaction.Commit();
}

Purely aesthetic and less-typing point of view and to let the 'using' catch an exception then rollback, dispose and re-throw.

Or am I going mad, and it's getting late?

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 12-Nov-2007 04:05:02   

I think that's no directly possible. However you would be interested in .NET 2.0 System.Transactions support and TransactionScope. Please read LLBLGenPro Help - Using generated code - Transactions - .NET 2.0: System.Transactions support.

David Elizondo | LLBLGen Support Team
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 12-Nov-2007 11:22:30   

Transaction (the LLBLGen Pro object) does rollback on dispose. (same for DataAccessAdapter, which also rolls back an open transaction when Dispose is called).

For readability, I'd still use the try/catch/finally (and beware: don't use throw ex;, use throw; ) the main reason is that there are scenario's where you can't rollback yourself, because the db already has rolled back the connection, for example in sqlserver with an error with severity level 16 or higher (e.g. fk violation with delete). Sqlserver then rollsback the transaction in progress and the client side ado.net object has no clue that this happened, and gets 'zombied' (there's even code in sqltransaction to check if it's a zombie wink ).

Frans Bouma | Lead developer LLBLGen Pro
louthy
User
Posts: 61
Joined: 02-Aug-2005
# Posted on: 18-Dec-2007 03:29:19   

Thanks for the reply Frans. Out of interest, why do you think it's more readable? Or do you mean it's more transparent what's happening? I personally find the try/catch/finally blocks a bit messy when used with a transaction.

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 18-Dec-2007 10:39:02   

Transparant and Readable might be used interchangeably. I think Frans ment Transparantly Readable simple_smile

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 18-Dec-2007 11:30:06   

With 'readable' I mean: easy to understand: what's going on is right in front of you without any magic behind the scenes. simple_smile

Frans Bouma | Lead developer LLBLGen Pro
enerata
User
Posts: 6
Joined: 29-Aug-2006
# Posted on: 23-Dec-2009 17:29:44   

In http://www.eggheadcafe.com/software/aspnet/31104178/iszombied-this-sqltransa.aspx I see that the try/catch idiom is suggested to be used around the Rollback() call to catch the "Transaction has completed" error and that seems reasonable.

It seems though that BaseEntity.Save(IPredicate,bool) does not use try/catch around RollBack(), and if there is an SQL error that triggers SQL Server to rollback the transaction, there is no chance to see the real error because the "Transaction has completed" exception hides it.

We have seen this error occasionally when calling Save(true) on entities that did not participate any transaction and we are concerned about the behavior of Save() and other LLBLGen methods that also create and manage their own transactions, such as UnitOfWork.Commit().

Our observations were made with "LLBLGen Pro .NET 2.0+ ORM Support Classes Library" version 2.6.9.903.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 24-Dec-2009 12:09:44   

How would a try/catch around the rollback give you more info than the raw exception that's thrown by the rollback? if that exception has no info, nothing will gain more info. Or I might have misunderstood you what you meant.

Frans Bouma | Lead developer LLBLGen Pro
enerata
User
Posts: 6
Joined: 29-Aug-2006
# Posted on: 31-Dec-2009 17:30:16   

It will not give us any information about the rollback exception. On the contrary, it will hide that information and allow us to re-"throw;" the exception that caused us to rollback in the first place.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 04-Jan-2010 08:44:30   

I had to re-re-read what you said and it finally was clear to me what you meant (and that on a monday morning at 8:30 am sunglasses ). Ironically you link to a post I wrote in a usenet thread 2 years ago simple_smile

To recap: the exception causing the failure of the transaction is not reaching your code as the catch clause causes an exception as well (due to the sqlserver rollback which makes the transaction object a zombie) and the original exception is therefore lost.

This is indeed a fair concern. The only problem is: the rollback failure is useful information too. Would you like to see the rollback exception with as inner exception the real exception (I think this is the preferred setup), or just the original exception and the rollback exception should be swallowed (IMHO less preferable)

Frans Bouma | Lead developer LLBLGen Pro
enerata
User
Posts: 6
Joined: 29-Aug-2006
# Posted on: 04-Jan-2010 18:31:50   

Happy new year.

Having the original exception as InnerException of the rollback exception seems more correct to me, too, because it gives all available information to the developer.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 05-Jan-2010 10:18:52   

Happy 2010 to you too simple_smile

I thought about using the original exception as the inner exception, but that makes writing code for it a bit more tedious, as the developer will prepare for the original exception, but not for the zombie-originating exception (as that's a result of sqlserver killing off the transaction on its own and MS refusing to implement some kind of low-level protocol for signaling that back in their low-level communication protocol).

but it is a bit backwards, I admit: the originating exception should be the inner exception by default.

I'll think about this some more and get back to you.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 05-Jan-2010 13:55:54   

Hmmm disappointed When the RollBack fails, there are two exceptions in scope: the original one which triggered the rollback and the exception thrown by the failed rollback. However, it's not possible to wrap both and keep stacktraces, as you can't alter an Exception object (as it only has readonly properties). The exception which triggered the rollback is already the wrapper around the sql exception (so an ORMQueryExecutionException) so what we've decided to do instead is swallow the InvalidOperation exception thrown by DbTransaction.Rollback() and let all other exceptions bubble upwards. The reason for doing this is also that the operation on the entities participating in the transaction is then done properly (as otherwise this logic is never called, as the exception is moving the contol flow outside Rollback) and re-trying code is more difficult due to this.

Rollback has checks which avoid rolling back a transaction which isn't in progress, so invalidoperation exceptions only occur when the server terminated the transaction/connection. The entities should then all be brought back into the pre-transaction state.

I'll attach a new build when this code is in the runtime.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 05-Jan-2010 14:08:47   

Please use the attached dll.

Frans Bouma | Lead developer LLBLGen Pro
enerata
User
Posts: 6
Joined: 29-Aug-2006
# Posted on: 07-Jan-2010 15:21:11   

Thank you a lot for the quick fix.

Will this fix be part of the next LLBL 2.6 patch? If yes, when should we expect this patch to come out?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 08-Jan-2010 10:27:48   

enerata wrote:

Thank you a lot for the quick fix.

Will this fix be part of the next LLBL 2.6 patch? If yes, when should we expect this patch to come out?

You got an official build of the main trunk, so the next build release will have the exact same dll as you got, so use it in production, as it's the same we would have released now if we would have released a full build today. simple_smile

Frans Bouma | Lead developer LLBLGen Pro