NHibernate Transactional Boundaries
Wednesday, October 14, 2009 at 8:29AM
Weston M. Binford III

In NHibernate Bootstrapping with StructureMap, I did not address the issue of transactional boundaries. The example had very simple controller actions that managed their own commits. However, this question on StackOverflow left me wondering who should be responsible for the commit?

Sharp Architecture’s Approach

Sharp Architecture is an excellent “architectural foundation for building maintainable web applications with ASP.NET MVC”. It has an Action Filter called Transaction that starts a transaction in the OnActionExecuting event, and then commits if no exception occurred. Otherwise, it explicitly rolls the transaction back. In fact, the Implicit transactions thread in the Sharp Architecture Google group discusses the Transaction attribute and some of the issues using it. The Transaction attribute provides the functionality that I want, but it requires the developer to decorate each Action method with an attribute. Why not make the HttpModule that creates and disposes of the Unit of Work handle the commit?

Modified Bootstrapping Example

I have modified the Bootstrapping NHibernate with StructureMap example from my previous post to do just that. Now, the NHibernateModule is responsible for calling Commit() on the UnitOfWork. Here is the NHibernateModule’s new Dispose method:

public void Dispose()
{
    _unitOfWork.Commit();
    _unitOfWork.Dispose();
}

The only addition is the call to the _unitOfWork.Commit(). However, now that the NHibernateModule is responsible for the commit, the developer can not abort an existing transaction. So, I added a Rollback() method to the IUnitOfWork class. The concrete implementation, UnitOfWork, calls _transaction.Rollback().

One final change to the UnitOfWork prevents it from throwing an exception if the developer explicitly calls commit by checking the ITransaction’s IsActive property before attempting to commit. Here is the UnitOfWork’s new Commit method:

public void Commit()
{
    if (_transaction.IsActive)
        _transaction.Commit();
}

Multi-Transaction Unit of Work

There is still one issue nagging at me. Once the developer commits the unit of work, the transaction is closed. The FubuTasks example in the fubumvc-contrib project solves this problem by starting a new transaction once the existing transaction is committed. Here is the source for FubuTask’s NHibernateUnitOfWork. I have talked to Chad Myers about this implementation and he has moved away from the idea of handling rollback in general. In any event, I don’t like the idea of starting a new transaction because I don’t think there should be one transaction per request. At the same time, I am preventing the developer from using my unit of work for more than one transaction. At least for now, opening a new transaction is a YAGNI for me. What do you think?

The full source code with these changes are available in the mvbalaw-commons project here.

Tags:

kick it on DotNetKicks.com
Article originally appeared on Weston Binford (http://trason.net/).
See website for complete article licensing information.