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.
- Efficient data access
- Properly manager concurrency problems
- 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);
}
}