So here is my current UnitOfWork implementation. This one makes use of the somewhat new current_session_context_class feature. I think this is quite simple compared to some of the others you will find.
public interface IUnitOfWork : IDisposable
{
IUnitOfWork Start();
void BeginTransaction();
void CommitTransaction();
void RollbackTransaction();
}
public class UnitOfWork : IUnitOfWork
{
#region Dependencies
public ISessionFactory SessionFactory
{
get;
set;
}
#endregion
#region IUnitOfWork Members
public virtual void BeginTransaction()
{
var session = SessionFactory.GetCurrentSession();
if ( !session.Transaction.IsActive )
{
session.BeginTransaction();
}
}
public virtual void CommitTransaction()
{
var session = SessionFactory.GetCurrentSession();
if ( session.Transaction.IsActive )
{
session.Transaction.Commit();
}
}
public void RollbackTransaction()
{
var session = SessionFactory.GetCurrentSession();
if ( session.Transaction.IsActive )
{
session.Transaction.Rollback();
}
}
public IUnitOfWork Start()
{
if ( !CurrentSessionContext.HasBind(SessionFactory) )
{
var session = SessionFactory.OpenSession();
session.FlushMode = FlushMode.Commit;
CurrentSessionContext.Bind(session);
}
return this;
}
#endregion
#region IDisposable Members
public void Dispose()
{
var session = CurrentSessionContext.Unbind(SessionFactory);
var transaction = session.Transaction;
if ( transaction.IsActive )
{
transaction.Dispose();
}
session.Dispose();
}
#endregion
}
All that’s required is this in the hibernate config section:
(for web apps):
<property name="current_session_context_class">web</property>
(for pretty much anything else):
<property name="current_session_context_class">thread_static</property>
and just the barebones bootstrapping:
var sessionFactory = new Configuration().Configure().BuildSessionFactory();
Of course, to get this to work you need to register that sessionFactory instance into your IoC container, and register the UnitOfWork type with the container with a transient lifecycle.
From there you can either explicitly create and dispose IUnitOfWork instances for each operation, or set up a HttpModule to create one at the start of each request and dispose of it in the end_request event.