NHibernate with TransactionScope

Andy White picture Andy White · Mar 14, 2009 · Viewed 19.8k times · Source

Can anyone give me a quick overview of using TransactionScope with NHibernate? Do I need to do anything special with the session/IEnlistmentNotification/etc. to get this to work? Are there any pitfalls that I should worry about? For example, can I replace all of my hibernate transactions:

var transaction = session.BeginTransaction();
try
{
    // code
    transaction.Commit();
}
catch (Exception)
{
    transaction.Rollback();
}

with this?:

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

Answer

Iain picture Iain · Nov 3, 2010

I have been using nHibernate 2.1 for awhile, and after a few production issues and trying quite a few variations, we have settled on the following method, as per Avoiding Leaking Connections With NHibernate And TransactionScope:

        using (var scope = new TransactionScope(TransactionScopeOption.Required))
        {
            using (var session = sessionFactory.OpenSession())
            using (var transaction = session.BeginTransaction())
            {
                // do what you need to do with the session
                transaction.Commit();
            }
            scope.Complete();
        }

As we are using MSMQ and WCF so we had to use the ambient transaction.

We found that not using session.BeginTransaction() caused a connection leak. We also found that re-using a session after committing a transaction caused a race condition (nHibernate is not thread safe and DTSC Commits/Rollbacks occur on a background thread).