views:

61

answers:

2

While creating a repository by using NHibetnate(or, whatever), should I keep explicit BeginTransaction(), Commit(), Rollback() like the following?

public class NHibernateRepository<T> : IRepository<T>
{
    private NHibernate.ISession _session;

    public NHibernateRepository()
    {
        _session = NHibernateSessionManager.Instance.GetSession();
        _session.BeginTransaction();
    }

    public void Save(T obj)
    {
        _session.Save(obj);
    }

    ... ... ... ... ... ... ...

    public void Commit()
    {
        if (_session.Transaction.IsActive)
        {
            _session.Transaction.Commit();
        }
    }

    public void Rollback()
    {
        if (_session.Transaction.IsActive)
        {
            _session.Transaction.Rollback();
            _session.Clear();
        }
    }

    public void BeginTransaction()
    {
        Rollback();
        _session.BeginTransaction();
    }
}

Or, should I write my persistence methods like this?

public class Repository<T> : IRepository<T>
    {
        ISession _session;

        public Repository()
        {
            _session = SessionFactoryManager.SessionFactory.OpenSession();
        }

        private void Commit()
        {
            if (_session.Transaction.IsActive)
            {
                _session.Transaction.Commit();
            }
        }

        private void Rollback()
        {
            if (_session.Transaction.IsActive)
            {
                _session.Transaction.Rollback();
                _session.Clear();
            }
        }

        private void BeginTransaction()
        {
            _session.BeginTransaction();
        }

        void IRepository<T>.Save(T obj)
        {
            try
            {
                this.BeginTransaction();

                _session.Save(obj);                

                this.Commit();
            }
            catch (Exception ex)
            {
                this.Rollback();

                throw ex;
            }            
        }

        ... ... ... ... ... ... ...
    }
}

Any suggestion? Can anyone compare these two approaches?

+2  A: 

Create a separate ITransactionManager, which will return My.ITransaction which you'll later commit and rollback as needed.

Currently you're just pollutin class interface and introducing complexity and weirdness (for instance, can I call BeginTransation in one repository and then Commit it in another?).

Anton Gogolev
"(for instance, can I call BeginTransation in one repository and then Commit it in another?)." Why is this needed? When you have an instance of one repository, you are expected to commit it before beginning another transaction. Do every class need to be such "bullet-proof" as you are talking about?
JMSA
+1  A: 

My approach is to let the UI/whatever control the scope of a unit of work (ISession) and pass the ISession into repository constructors as a dependency. That way a single unit of work can enlist as many repositories as needed in a transaction.

Jamie Ide