Introduction
Martin Fowler writes:
"When you're pulling data in and out of a database, it's important to keep
track of what you've changed; otherwise, that data won't be written back into
the database. Similarly you have to insert new objects you create and remove any
objects you delete."
and
"A Unit of Work keeps track of everything you do during a
business transaction that can affect the database. When you're done, it
figures out everything that needs to be done to alter the database as a result
of your work."
In NHibernate we have the Session object which is a Unit of
Work (UoW) container. The session object keeps track of all objects you load,
new objects you add, existing objects you delete and changes you make to any of
these objects. Only when flushing the session will the database
be altered (that is: will the necessary create, update and delete statements be
sent to the database).
Now, working directly with the NHibernate session object makes absolute
sense. But some times you rather want to abstract the data manipulation
interface from a specific infrastructure implementation à la NHibernate.
Note: most of the design ideas and implementation details
presented here originate from Ayende's
UnitOfWork implemented in the Rhino.Commons which you can get
here.
Design and Implementation (TDD)
Some thought about TDD
I want to implement a UnitOfWork pattern for NHibernate and I want to do it
by using TDD.
For a beginner (like I was myself not so long ago) it seems unnatural at the
beginning. We introduce a huge overhead you might think. You might also think
that we have to write at least double the code as when doing the development
without TDD. But wait until you have to start to debug your application... or
until the customer wants to have something changed in the application... or
until you have to re-factor you application... Then you will immediately see and
feel the benefits of a good test coverage.
Attention: Multi-Threading ahead
Please not that the implementation presented here is strictly
NOT thread safe!!! I want to reduce the complexity of this
first implementation. But I promise that in a following post
I'll show you how to make the implementation of the unit of work pattern thread
safe and thus useful for e.g. Web scenarios.
The UnitOfWork Class
To start with: I want to have an easy way to start a new
UoW, in any place of my application have access to the current
UoW and commit the business transaction represented by
my UoW. We can do this with a static class called UnitOfWork
![image]()
The method start creates and returns an instance of a
UnitOfWorkImplementor class which implements the interface
IUnitOfWork. As you can see then interface IUnitOfWork inherits
from IDisposable. So we can define that the business transaction is
ended when the UoW is disposed. Now, if we do nothing else then nothing should
happen, that is no changes should be propagated to the database. To commit a
business transaction we have to explicitly call a method of the UoW.
Let's call this method TransactionalFlush. In doing so all
changes recorded by the UoW are committed to the database in one go.
Now let's start to implement this! We are doing TDD, aren't we? So we will
write our first test (if you are not sure how to best setup a new solution for
TDD please consult this
post). I define a new solution with two projects as follows
![image]()
Add a class UnitOfWork_Fixture.cs to the test project and implement the first
test like this
[TestFixture]
public class UnitOfWork_Fixture
{
private readonly MockRepository _mocks = new MockRepository();
[Test]
public void Can_Start_UnitOfWork()
{
IUnitOfWork uow = UnitOfWork.Start();
}
}
Of course this test will not compile since you don't have the types
UnitOfWork and IUnitOfWork defined yet. Let Resharper create them for you (or
implement them by hand)
public static class UnitOfWork
{
public static IUnitOfWork Start()
{
throw new NotImplementedException();
}
public static IUnitOfWork Current { get; private set; }
}
public interface IUnitOfWork : IDisposable
{
}
Now the test will compile but it will fail! Of course, you haven't
implemented the Start method so far. In this method we must now create a new UoW
and return it to the caller. A UoW is a complex beast and should therefore be
constructed in a factory. So let's define a factory Interface IUnitOfWorkFactory
with a method Create which returns a UoW implementing the interface
IUnitOfWork.
public interface IUnitOfWorkFactory
{
IUnitOfWork Create();
}
since we want to test our UnitOfWork class in isolation we have to mock all
other dependencies line the unit of work factory. I'll use
Rhino.Mocks as my mocking framework (Please refer to
documentation here). I
want to test that when calling the start method of the UnitOfWork class the
factory gets called. So I extend my test function
[Test]
public void Can_Start_UnitOfWork()
{
var factory = _mocks.DynamicMock<IUnitOfWorkFactory>();
var unitOfWork = _mocks.DynamicMock<IUnitOfWork>();
// brute force attack to set my own factory via reflection
var fieldInfo = typeof(UnitOfWork).GetField("_unitOfWorkFactory",
BindingFlags.Static | BindingFlags.SetField | BindingFlags.NonPublic);
fieldInfo.SetValue(null, factory);
using(_mocks.Record())
{
Expect.Call(factory.Create()).Return(unitOfWork);
}
using(_mocks.Playback())
{
var uow = UnitOfWork.Start();
}
}
In the first two lines of code I mock the external dependencies of the
UnitOfWork class. Then I do something you should not do very often (but I have
good reasons doing so here and I promise it's the only time I'll do it in this
project...). I set a private field of the UnitOfWork class with a value by using
reflection. I could implement a public setter in the class but as I would only
need it for this test and I want to keep the class interface as simple as
possible I chose to do it via reflection.
In the record phase I define my expectation (namely that the factory create
method is called) and in the playback phase I invoke the Start method which I
want to test. The test will compile but fail to execute. I have not yet defined
the private static field _unitOfWorkFactory and I also do not call the factory.
So let's modify our code...
public static class UnitOfWork
{
private static IUnitOfWorkFactory _unitOfWorkFactory;
private static IUnitOfWork _innerUnitOfWork;
public static IUnitOfWork Start()
{
_innerUnitOfWork = _unitOfWorkFactory.Create();
return _innerUnitOfWork;
}
public static IUnitOfWork Current { get; private set; }
}
now the test will pass.
Since in all our test regarding the UnitOfWork class we will always need it
with an injected factory we define a new test fixture with a context setup for
our specific needs. We put the respective code in the
SetupContext and TearDownContext methods
[TestFixture]
public class UnitOfWork_With_Factory_Fixture
{
private readonly MockRepository _mocks = new MockRepository();
private IUnitOfWorkFactory _factory;
private IUnitOfWork _unitOfWork;
[SetUp]
public void SetupContext()
{
_factory = _mocks.DynamicMock<IUnitOfWorkFactory>();
_unitOfWork = _mocks.DynamicMock<IUnitOfWork>();
// brute force attack to set my own factory via reflection
var fieldInfo = typeof(UnitOfWork).GetField("_unitOfWorkFactory",
BindingFlags.Static | BindingFlags.SetField | BindingFlags.NonPublic);
fieldInfo.SetValue(null, _factory);
_mocks.BackToRecordAll();
SetupResult.For(_factory.Create()).Return(_unitOfWork);
_mocks.ReplayAll();
}
[TearDown]
public void TearDownContext()
{
_mocks.VerifyAll();
}
}
Note: in the second last line of the
SetupContext method we define that each time the method Create
of the factory object is called (by the UnitOfWork Start method) we want it to
return our predefined mocked _unitOfWork instance.
Trying to start a UoW if there is already one active should throw a
meaningful exception. This is the test
[Test]
public void Starting_UnitOfWork_if_already_started_throws()
{
UnitOfWork.Start();
try
{
UnitOfWork.Start();
}
catch (InvalidOperationException ex)
{ }
}
As a consequence we have to extend our Start method in the UnitOfWork
class
public static IUnitOfWork Start()
{
if (_innerUnitOfWork != null)
throw new InvalidOperationException("You cannot start more than one unit of work at the same time.");
_innerUnitOfWork = _unitOfWorkFactory.Create();
return _innerUnitOfWork;
}
Now I have another problem: After the test is finished the static field
_innerUnitOfWork of my UnitOfWork class is set
to a value other than null. This will have a undesired side
effect to the following test. I have to reset this field. Again in this special
case I'll do it via reflection to not clutter the interface of my class (static
classes are difficult more complex to deal with in TDD than non static
classes...). We do reset our UnitOfWork class in the TearDownContext method
[TearDown]
public void TearDownContext()
{
_mocks.VerifyAll();
// assert that the UnitOfWork is reset
var fieldInfo = typeof(UnitOfWork).GetField("_innerUnitOfWork",
BindingFlags.Static | BindingFlags.SetField | BindingFlags.NonPublic);
fieldInfo.SetValue(null, null);
}
Next we want to be able to access the current unit of work. As usual we first
implement a test
[Test]
public void Can_access_current_unit_of_work()
{
IUnitOfWork uow = UnitOfWork.Start();
var current = UnitOfWork.Current;
Assert.AreSame(uow, current);
}
You can figure out what code you need to implement for the test to pass.
We also want to assert that when accessing the current UoW if no UoW has been
started that a meaningful exception is thrown
[Test]
public void Accessing_Current_UnitOfWork_if_not_started_throws()
{
try
{
var current = UnitOfWork.Current;
}
catch (InvalidOperationException ex)
{ }
}
now my implementation of the Current property in the UnitOfWork class is as
follows
public static IUnitOfWork Current
{
get
{
if (_innerUnitOfWork == null)
throw new InvalidOperationException("You are not in a unit of work.");
return _innerUnitOfWork;
}
}
Next we want a property on the class which tells us whether a UoW is started
or not. The test for it
[Test]
public void Can_test_if_UnitOfWork_Is_Started()
{
Assert.IsFalse(UnitOfWork.IsStarted);
IUnitOfWork uow = UnitOfWork.Start();
Assert.IsTrue(UnitOfWork.IsStarted);
}
It's getting boring isn't it... But this is the way TDD
works. You always think (hard) on what you need and then you implement the test
with which you can proof that you get it as you want it. Only then you implement
the functionality needed to fulfill the test. If you do so you automatically
follow the YAGNI principle (you ain't gona need it) that is you
only implement the code you really need!
We can fulfill the test like so
public static bool IsStarted
{
get { return _innerUnitOfWork != null; }
}
The UnitOfWork class is now a perfect wrapper for the NHibernate session
object. Though for some advance scenarios I would like to have access to the
session object related to my UoW. As a consequence I'll implement a read only
property CurrentSession in the UnitOfWork class. Lets again start with the
test
[Test]
public void Can_get_valid_current_session_if_UoW_is_started()
{
using (UnitOfWork.Start())
{
ISession session = UnitOfWork.CurrentSession;
Assert.IsNotNull(session);
}
}
and the implementation
public static ISession CurrentSession
{
get { return _unitOfWorkFactory.CurrentSession; }
internal set { _unitOfWorkFactory.CurrentSession = value; }
}
Note that I have just delegated the call to the factory class. Thus to make
the test pass I have to add two additional lines to the SetupContext method of
the test fixture where I mock a session object and setup the result for a call
to the property CurrentSession of the factory.
[SetUp]
public void SetupContext()
{
_factory = _mocks.DynamicMock<IUnitOfWorkFactory>();
_unitOfWork = _mocks.DynamicMock<IUnitOfWork>();
_session = _mocks.DynamicMock<ISession>();
// brute force attack to set my own factory via reflection
var fieldInfo = typeof(UnitOfWork).GetField("_unitOfWorkFactory",
BindingFlags.Static | BindingFlags.SetField | BindingFlags.NonPublic);
fieldInfo.SetValue(null, _factory);
_mocks.BackToRecordAll();
SetupResult.For(_factory.Create()).Return(_unitOfWork);
SetupResult.For(_factory.CurrentSession).Return(_session);
_mocks.ReplayAll();
}
That's all we need for the moment regarding the UnitOfWork class. Next topics
will be the the implementation of the UnitOfWorkFactory class and then of the
UnitOfWorkImplementor class. The details will be presented in the next post to
this blog. So keep ready...
Part 2
Design and Implementation
The Unit Of Work Factory
The creation of a unit of work instance is a complex process and as such is a
good candidate for a factory.
Since a UoW (Unit of Work) is basically a wrapper around a NHibernate session
object I'll need to open such a session whenever I start a new UoW. But to be
able to get such a session NHibernate has to be configured and a NHibernate
Session Factory has to be available. The interface of my UoW factory is defined
as follows