software development

Simple Unit of Work implementation

##Simple Unit of Work implementation##

The Unit of Work pattern is an important part of many architecture designs. I refer you to Martin Fowler’s [description](http://martinfowler.com/eaaCatalog/unitOfWork.html) for more details on the pattern.

Typically, a unit of work is ‘opened’ at the beginning of an operation in an application, which I’ll call an entry point, and closed when that operation ends, the exit point. A simple example is with a web application: the user requesting some resource from the web application is the entry point.

In ASP.Net, this entry point is explioit and accessible, the HTTPApplication’s Begin_Request method. Symmetrically, the End_Request method provides an exit point. These methods provide convenient locations in which to open and close the unit of work.

What’s also very nice about these methods is by the time the End_Request method is closed, we have finished making changes to the Response sent by the server. We are protected from things like lazy loading exceptions being thrown due to closed sessions.

In my current project, the application is a Windows service. The Windows service hosts three different ‘operation stacks’, each of which has a different entry point:

– A request to a webservice (powered by [ServiceStack](www.servicestack.net))

– Receiving a message from a Bus or queue (powered by [Mass Transit](http://masstransit-project.com/) or in-memory with [BlockingCollection](http://msdn.microsoft.com/en-us/library/dd267312.aspx)

– A timer ticking (database records are processed every *X* minutes

Each of these stacks runs on a different thread.

This project uses [NHibernate](http://www.nhforge.org/). My main concern with unit of work is the timing of database connections and sessioning, and associated issues like lazy loading of graphs. NHibernate’s ISession is already an implementation of the Unit of Work pattern. However I find it is not enough on its own.

I’ll use some code to illustrate why.

The majority of the DoWork() method is taking up with unit of work housekeeping: opening the session, binding the contextual session etc. There is in fact only one line in the whole method (dependency.SomeMethod()) which actually does any work. This is problematic for several reasons:

– Unit of work housekeeping is definitely not the concern of the DoWork() method or the MyClass class (violation of principle of Separation of Concerns).

– The same housekeeping code would have to be repeated in every entry point (at least five times currently).

– It couples MyClass (and all other entry points) to NHibernate.

Fortunately, it isn’t too difficult to refactor this into a more palatable solution.

The first thing is to move all the actual unit of work code into its own class:

This would be used like this (note that the Func dependency is injected by a Dependency Injection container):

We’ve removed the NHibernate dependency, but there’s still a lot of housekeeping code. A further refactoring, with the help of an Action and lambdas makes it a lot cleaner. First, the unit of work usage:

Much less housekeeping, and the Separation of Concerns violation isn’t as bad. The unit of work class is refactored to:

The addition of the Begin(Action action) class makes the consumption of the unit of work much cleaner: All the housekeeping takes place within the UnitOfWork class, and the actual method representing the work to be done is called as a Delegate.

This pattern of passing in the work method as an Action is easily repeated in the other entry point methods in the system. There is little violation of Separation of Concerns, the calling code has no inkling that NHibernate is involved, and the amount of repeated code becomes tiny.

An elegant solution in my opinion!

Advertisements

One thought on “Simple Unit of Work implementation

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s