Friday, February 04, 2011

Nested Transaction Handling with NHibernate

NHibernate doesn’t have inbuilt support for nested transaction (or I am not using latest version). But, with little compromises, you can create a class that enables almost everything what you really need. I am using NHibernateSessionManager which you can find here: http://www.codekeep.net/snippets/8b94e3e0-3ffd-4b59-b6ce-ed4d46158a7c.aspx
    public class SmartTransaction
    {
        bool _transactionOwner =false;
        bool _transactionActive = false;

        public bool IsActive
        {
            get
            {
                return _transactionActive;
            }
        }

        public void Begin()
        {
            if (_transactionActive) return; //return to bad programer's code

            try
            {
                _transactionOwner = !NHibernateSessionManager.Instance.HasOpenTransaction();
                if (_transactionOwner)
                    NHibernateSessionManager.Instance.BeginTransaction();
                _transactionActive = true;
            }
            catch
            {
                _transactionOwner = false;
                _transactionActive = false;
                throw;
            }
        }

        public void Commit()
        {
            if (!_transactionActive || !NHibernateSessionManager.Instance.HasOpenTransaction())
            {
                _transactionActive = false;
                return;
            }

            try
            {
                if (_transactionOwner)
                    NHibernateSessionManager.Instance.CommitTransaction();
            }
            catch //when you don't know what you are committing to.
            {
                NHibernateSessionManager.Instance.RollbackTransaction(); 
                throw;
            }
            finally
            {
                _transactionActive = false;
            }
        }

        public void Rollback()
        {
            _transactionActive = false;

            if (!NHibernateSessionManager.Instance.HasOpenTransaction())
                return;
            NHibernateSessionManager.Instance.RollbackTransaction();
        }
    }


Benefits:

1. When writing a method, you need not to worry about context of calling method. You can just begin transaction of SmartTransaction class. If calling method has started transaction already, SmartTransaction doesn’t begin the transaction, but if something goes wrong, it will rollback entire transaction (of calling method).


2. You need not to worry if method you are calling needs transaction wrapping. As with SmartTransaction class, if method you are calling needs transaction wrapping, it will have transaction wrapping using SmartTransaction class.