Saturday, January 19, 2013

Unit of Work Pattern

There are patterns considered as Domain Driven Design patterns. I decided to blog common DDD design patterns, and would be happy to have your thoughts or questions on comments. This post introduces Unit of Work pattern.

Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems. (Martin Fowler)

  • Loading an object from the database registers the object as clean
  • Any changes to clean object register the object as dirty
  • Creating a new object registers the object as new
  • Deleting an existing object registers the object as deleted
  • Commit opens a transaction, does any concurrency checking, and persists changes to the database

  • When you want to keep track of the changes that may affect a database and update database at the end.
  • Coordinate with message queues and transaction monitors.

  • Unit of Work is the natural place to sort out the update order.
  • To avoid multiple database calls,and leave all updates to the end.
  • Keeps all changes information in one place.

  • Using Unit of Work in a multithreading environment is tricky and one approach is to make sure that more than one thread can not get access a Unit of Work.
  • Passing the Unit of Work around is tedious, and it's usually no problem to have the Unit of Work present in some kind of session object.

Sample Code
Assume you would like to track changes in your domain objects, and observe interested domain object changes in a unit of work and at the time of unit of work completion do something with the changes.

Here are the domain entities:

To make the domain entities changes observable, an entity state tracker is defined to be used as an interceptor when the entity is changing:

Castle dynamic factory is used to set up the entity state tracker as an interceptor and here is the entity proxy factory:

Now it is time to use Unit of work pattern to integrate all of these together and have an entity change tracker unit of work:

And finally a sample usage of the Entity change tracker unit of work:

Here is the output: