NHibernate leaking connections with UnitOfWork pattern and transactions
Recently I’ve been using NHibernate in a project at work along with the unit of work pattern in an asp.net mvc site. Only 1 instance of the UoW is created per request and disposed of at end of the request.
In fact here is a UoW class we’re using:
public class UnitOfWork : INHibernateUnitOfWork
{
/// <summary>
/// The session factory
/// </summary>
private readonly ISessionFactory sessionFactory;
/// <summary>
/// The current transaction
/// </summary>
private readonly ITransaction transaction;
/// <summary>
/// Gets the session.
/// </summary>
/// <value>The session.</value>
public ISession Session { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="UnitOfWork"/> class.
/// </summary>
/// <param name="sessionFactory">The session factory.</param>
public UnitOfWork(ISessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
Session = this.sessionFactory.OpenSession();
Session.FlushMode = FlushMode.Auto;
transaction = Session.BeginTransaction();
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
transaction.Dispose();
}
/// <summary>
/// Commits this instance.
/// </summary>
public void Commit()
{
if (!transaction.IsActive)
{
throw new InvalidOperationException("No active transation");
}
/transaction.Commit();
}
/// <summary>
/// Rollbacks this instance.
/// </summary>
public void Rollback()
{
if (transaction.IsActive)
{
transaction.Rollback();
}
}
}
As you can see in the constructor we create a new NHibernate transaction and dispose of it when the request ends (by calling the dispose method).
The problem with this is that it created a connection with an open transaction but never closed it. Any way to resolve this we removed the use of transactions (until such a time they are working or we’ve figured out a suitable alternative). Two changes where made to the dispose and commit method to clean up the session instance and make sure the data is flushed.
public void Dispose()
{
Session.Dispose();
}
public void Commit()
{
Session.Flush();
}
Note: This project also is using the Velocity cache provider and by removing the transactions / replacing the code the caching mechanisms still work.

Trackbacks & Pingbacks