Achieving NHibernate Nested Transactions Behavior

3.7k views Asked by At

I'm trying to achieve some kind of nested transaction behavior using NHibernate's transaction control and FlushMode options, but things got a little bit confusing after too much reading, so any confirmation about the facts I list below will be very usefull.

What I want is to open one big transaction that splits in little transactions. Imagine the following scenario:

  • TX1 opens a TX and inserts a Person's record;
  • TX2 opens a TX and updates this Person's name to P2;
  • TX2 commits;
  • TX3 opens a TX and updates this Person's name to P3;
  • TX3 rollbacks;
  • TX1 commits;

I'd like to see NH sending the INSERT and the TX2 UPDATE to the database, just ignoring what TX3, as it was rolled back.

I tried to use FlushMode = Never and only flushing the session after the proper Begins/Commits/Rollbacks have been demanded, but NH always update the database with the object's final state, independent of commits and rollbacks. Is that normal? Does NH really ignores transactional control when working with FlushMode = Never?

I've also tried to use FlushMode = Commit and openning the nested transactions, but I discovered that, because ADO.NET, the nested transactions are, actually, always the same transaction.

Note that I'm not trying to achieve a "all or nothing" behavior. I'm looking more to a savepoint way of working. Is there a way to do that (savepoints) with NH?

Thank you in advance.

Filipe

2

There are 2 answers

0
jfneis On BEST ANSWER

Just to don't leave this question open forever, I'll post the solution that we've adopted.

We have a unit of work like container that manages the nested transaction behavior. Depending on the kind of treatment that we want, it creates (or not) new sessions. By example:

  • Continue on error: if we want that even if on a transaction error the other ones commits, the UoW container uses different sessions for each "transaction" and flushes every tx in the end of its work;
  • Rollback on error: if we want that on a session rollback (because of an error or a business rollback) every other transaction gets rolled back, the UoW container uses the same session for all of the nested transactions and rolls back everybody in the end.

It's important to say that the "transaction" that this UoW manipulates isn't the NH (ADO.NET) transaction directly. We've created an abstraction of a transaction so the manipulation code "votes" if our transaction might be commited or rolled back, but the real action just occurs in the end of everything, based on the selected error strategy.

We know that this usage isn't very common and only fits on specific scenarios (in our case it's an integration scenario with batch processing), so I'll now post code. If anyone thinks that this implementation can help, please, send me a message and I'll be glad to share the code.

Regards,

Filipe

3
Jamie Ide On

NHibernate does not support nested transactions. Each ISession can have at most one active transaction. I'm not sure what you;re trying to accomplish because your example scenario doesn't make sense to me. Committing transaction 1 after the insert would have the same effect.