Wednesday 31 December 2014

Unit of Work Design Pattern

I thought of start a blog sessions on Design Patterns because understanding such is very important when it comes to the design of software systems. Lets start with the Unit OF Work Pattern. 

Unit of work design pattern is widely used pattern especially in the data access scenarios.  Following are the key points of advantages of this pattern.
  1. Efficient data access
  2. Properly manager concurrency problems
  3. Manage transactions

Using a UOW , we can limit the db calls specially when saving data. We can implement a commit method in the UOW and do atomic transaction to the db which may saves in different tables. We can use the same principle to manage business transactions as well. Assume we are having different data providers from db, web service and windows service. Using the UOW ( again using commit method ) we can manage an atomic transaction over different entities. 


                                                             Figure 1 : Unit Of Work          
           
                                
When it comes to .Net data access , the technologies such as Entity Framework adopted the UOW pattern by default. Following is an example.

var context = new ObjectContext(_connectionString);

            var employeeOne =
                context.CreateObjectSet<Employee>()
                    .OrderByDescending(e => e.registeredDate)
                    .First();

            employeeOne.registeredDate = employeeOne. registeredDate.AddDays(1);

            var lastEmployee =
                context.CreateObjectSet<Employee>()
                    .OrderBy(e => e.HireDate)
                    .First();

            lastEmployee.FirstName = "James";


            context. SaveChanges();

In this example , context.saveChanges() is the commit method in the UOW. We can see that two changes effected to SaveChanges the employeeOne and lastEmployee objects getting saved at once later in the SaveChanges method.

Implementing UOW pattern with Entity Framework

Even though I have given the above simple example to understand the UOW , the practical usage of this pattern is bit more complex. The main objective of the UOW is grouped different entities in to one logical business unit. Rather than tightly couple with data objects as in this example , it is always better perform an implementation to a well-structured interface.

Following example depicts more practical usage of UOW using Entity framework.

IUnitOfWork

     public interface IUnitOfWork {
            IRepository<Employee> Employees { get; }
            IRepository<TimeCard> TimeCards { get; }
            void Commit();
        }

This is the basic structure of our sample UOW which consisting two entities. We would be doing all operations to those entities and the atomic transaction is implemented using the Commit() method. We are using the repository pattern for to implement two entities in this example.  These two patterns are blending together well in most of the implementations.

Following is an example of implementation of the UOW.

public class UnitOfWorkImpl : IUnitOfWork {
        public UnitOfWorkImpl () {
            var connectionString =
                ConfigurationManager
                    .ConnectionStrings[ConnectionStringName]
                    .ConnectionString;

            _context = new ObjectContext(connectionString);
            _context.ContextOptions.LazyLoadingEnabled = true;
        }

        public IObjectSet<Employee> Employees {
            get { return _context.CreateObjectSet<Employee>(); }
        }

        public IObjectSet<Salary> TimeCards {
            get { return _context.CreateObjectSet<Salary>(); }
        }

        public void Commit() {
            _context.SaveChanges();
        }

        readonly ObjectContext _context;
        const string ConnectionStringName = "MyConStr";
    }
This can be implemented using other technologies as well such as NHibernate, WCF Data services etc..

Following is an example of how we can use the UOW implementation class.

public partial class EmployeeController : Controller {


        public EmployeeController()
            : this(new SqlUnitOfWork()) {

        }

        public EmployeeController(IUnitOfWork unitOfWork) {
            _unitOfWork = unitOfWork;
        }

       
        public ViewResult Index() {
            var model = _unitOfWork.Employees
                                   .OrderBy(e => e. registeredDate)                  
                                   .Include("Salary");
            return View(model);
        }

  [HttpPost]
        public ActionResult Edit(int id, FormCollection collection) {
            var model = _unitOfWork.Employees.Single(e => e.Id == id);
            TryUpdateModel(model, new string[] { "FirstName", "registeredDate" });
            if (ModelState.IsValid) {
                _unitOfWork.Commit();
                return RedirectToAction("Index");
            }

            return View(model);
        }

}