Revisiting the Repository and Unit of Work Patterns with Entity Framework

June 21, 2010

Revisiting the Repository and Unit of Work Patterns with Entity Framework


In the past I wrote twoRevisiting the Repository and Unit of Work Patterns with Entity Framework
posts about the
Repository and the
Unit of Work patterns
(here and here). Today
I want to show a better
and less naive solution
for imposing the Unit of Work and the Repository patterns with
Entity Framework.


Revisiting The Repositoy Implementation


In the Repository pattern, I added to the interface two new
methods for adding and removing an entity:



public interface IRepository<T>
                where T : class
{
  T GetById(int id);
  IEnumerable<T> GetAll();
  IEnumerable<T> Query(Expression<Func<T, bool>> filter);    
  void Add(T entity);
  void Remove(T entity);
}

Also I’ve changed the return type of the Query from IQueryable
to IEnumerable in order not to enable additional composition
on that query that will hit the database.
The implementation of the Repository itself will change as follows:



public abstract class Repository<T> : IRepository<T>
                                  where T : class
{
  #region Members
 
  protected IObjectSet<T> _objectSet;
 
  #endregion
 
  #region Ctor
 
  public Repository(ObjectContext context)
  {
    _objectSet = context.CreateObjectSet<T>();
  }
 
  #endregion
 
  #region IRepository<T> Members
 
  public IEnumerable<T> GetAll()
  {
    return _objectSet;
  }
 
  public abstract T GetById(int id);
 
  public IEnumerable<T> Query(Expression<Func<T, bool>> filter)
  {
    return _objectSet.Where(filter);
  }
 
  public void Add(T entity)
  {
    _objectSet.AddObject(entity);
  }
 
  public void Remove(T entity)
  {
    _objectSet.DeleteObject(entity);
  }
 
  #endregion

One of the things to notice is that I hold an IObjectSet as my data 
member of the Repository itself instead of holding the context like
in my previous post. The IObjectSet is a new interface in EF4
which helps to abstract the use of the created entity sets.
Now the Repository is better implemented and looks like an
in-memory collection as it was suppose to be. If I need more specific
methods I can inherit from this Repository implementation and add the
desired functionality. As you can see I don’t implement the GetById
method and enforce my concretes to implement it.
The DepartmentRepository from the previous post will look like:



public class DepartmentRepository : Repository<Department>
{
   #region Ctor
 
   public DepartmentRepository(ObjectContext context)
     : base(context)
   {
   }
 
   #endregion
 
   #region Methods
 
   public override Department GetById(int id)
   {
     return _objectSet.SingleOrDefault(e => e.DepartmentID == id);
   }
 
   #endregion
}

Revisiting The Unit of Work Implementation


After we have our Repository we would like to create a
Unit of Work to hold the application repositories and to
orchestrate the persisting of data for some business transactions.
The new interface for the Unit of Work will look like:



public interface IUnitOfWork
{
  IRepository<Department> Departments { get; }    
  void Commit();
}

By of course if you have more repositories in your application you
will add them to the IUnitOfWork (in the example I only have the
departments repository). Now the implementation of the Unit of Work
won’t be a part of the repository (like in the old post) and will look like:



public class UnitOfWork : IUnitOfWork
{
  #region Members
 
  private readonly ObjectContext _context;
  private DepartmentRepository _departments;
 
  #endregion
 
  #region Ctor
 
  public UnitOfWork(ObjectContext context)
  {
    if (context == null)
    {
      throw new ArgumentNullException(“context wasn’t supplied”);
    }
 
    _context = context;
  }
 
  #endregion
 
  #region IUnitOfWork Members
 
  public IRepository<Department> Departments
  {
    get
    {
      if (_departments == null)
      {
        _departments = new DepartmentRepository(_context);
      }
      return _departments;
 
    }
  }
 
  public void Commit()
  {
    _context.SaveChanges();
  }
 
  #endregion
}

As can be seen the Unit of Work holds the ObjectContext but
you could use an IContext interface instead if you like to be more
abstract and with no dependency on Entity Framework at all. This can be
achieved by using the T4 templates that were provided in EF4 which you
will use to add the IContext interface implementation. The
Unit of Work has a constructor that can be injected using an IoC container.
The testing program will change into:



using (SchoolEntities context = new SchoolEntities())
{
  UnitOfWork uow = new UnitOfWork(context);
  foreach (var department in uow.Departments.GetAll())
  {
    Console.WriteLine(department.Name);
  }
 
  foreach (var department in uow.Departments.Query(d => d.Budget > 150000))
  {
    Console.WriteLine(“department with above 150000 budget: {0}”,
        department.Name);
  }
}

Some thing to notice here is that I create the context during
the running of the program. As I wrote earlier, this can be changed
to using an IoC container instead which will inject the constructor
dependency.


Summary


Lets sum up, this offered solution is much better then the naive
example I gave in the previous posts. It is much more testable and
abstract and as I wrote you could go further and use an IoC container
to inject the use of Entity Framework in the Unit of Work
implementation.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

14 comments

  1. James AlexanderJune 21, 2010 ב 21:04

    Gil,

    This is definitely one of the better suggestions I’ve seen for incorporating UoW, Repository and EF. One question I have though is how you’d recommend using this pattern along with eager loading in EF. For instance, if I have a type called Department with a collection or navigation property for Employees and want to get the instances of Department that has Employee’s with a salaray > $100K, how would you incorporate that functionality.

    Also lets say Department has a navigation property called Status and references a table with enum values.

    In most instances I want Status eagerly loaded so I’m only issuing one request to my DB server instead of lazy-loading it and issuing a second request. How would you incorporate eager loading into your UoW/Repository pattern?

    Reply
  2. DiegoJune 21, 2010 ב 23:28

    This way when Instantiating a unit of work I wouldn’t be creating all repositories of my application? This isn’t a bad thing thinking in performance?
    Please correct me if I’m wrong 🙂

    Reply
  3. Gil FinkJune 22, 2010 ב 8:11

    @Diego,

    The use of Lazy Load to create the repositories when they are needed isn’t a bad thing when thinking about performance. I create the resource (repository) when I need it and therefore save memory and time since I won’t create a resource that I’m not using. It can impact the performance only when the repository creation is very expensive. In the example, if the CreateObjectSet method is expensive then it will impact the performance of the first operation on the repository.

    Reply
  4. Gil FinkJune 22, 2010 ב 8:46

    @James Alexander,

    You can take the solution I offered and manipulate it for your needs. For example, you can create an interface of IDepartmentRepository which will iclude a specific contract for Departments and have a GetDepartmentsAndEmployees method (and also implement the IRepository interface). In the Unit of Work you’ll replace the IRepository with the IDepartmentRepository and you will have a solution for your eager loading problem. Of course this is more application specific solution and it is less generic but it still offers the testability of your data access layer.

    Another solution will be to create a new method on the IRepository interface like:
    IEnumerable QueryObjectGraph(Expression> filter, string children);
    In this method implementation you will use the Include method with the supplied children like:
    public IEnumerable QueryObjectGraph(Expression> filter, string children)
    {
    return _objectSet.Include(children).Where(filter);
    }
    Pay attention that in this solution you’ll have to replace the IObjectSet member to ObjectSet in order to have the Include method implementation.

    I hope this is what you seek.

    Reply
  5. Andrew HayJune 23, 2010 ב 2:36

    I wrote a quick ASP.Net MVC 2 app using your idea. It turns out that I needed to call .GetAll().ToList() to use the data in my strongly typed view.

    I expected the IEnumerable type to take care of this for me, but it’s acting like the type is IQueryable and failing because “The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.”

    Here’s what I did:

    public ActionResult Index()
    {
    IEnumerable list;

    using (var context = new NorthwindEntities())
    {
    var uow = new UnitOfWork(context);
    list = uow.Orders.GetAll(); // fails
    // list = uow.Orders.GetAll().ToList(); // works
    }

    return View(list);
    }

    What’s that all about?

    Regards,

    Andrew

    Reply
  6. Gil FinkJune 24, 2010 ב 8:09

    @Andrew Hay,

    Since I return the ObjectSet (which implement the IQueryable as well) as the IEnumerable the operation against the database is happening only when you use the set (the same happens in LINQ and this is deffered loading feature). For example when you enumerate the collection (or call the ToList method) it will trigger the query to the database. Since the ObjectSet is part of the ObjectContext which is responsible for database connectivity and it is also disposed in your case then you get the exception. The answer to the problem is to make the lifetime of the ObjectContext per request and dispose it when the request ends.

    Reply
  7. EdmilsonJune 26, 2010 ב 17:50

    Hi! very good post,

    I’m not sure but in the IUnitOfWork that is used for something?

    Now, one dummie question:

    In Asp. Net WebForms.
    Update is my question, I take back the entity from
    DB by the GetByID method, and fill all textboxs of my WebForm to perform the method GetByID I used some Event on my WebForm Page. now I changed some values on the textboxes and I want give the entity back to DB, so I have this Update button on my form. How do I keep the same Context of the UnitOfWork that toke the entity before give the Commit?

    I´ve tryed put the instance of que UnitOfWork at Page Scope instead some Event, but this is not working.

    thanks,

    Edmilson

    Reply
  8. Gil FinkJune 26, 2010 ב 19:43

    @Edmilson,
    The IUnitOfWork isn’t generic, the T slipped from my previous post example (and I removed it now).
    For the second question, my recommandetion for the lifetime of a context is per request and I wrote a post about it in the past. Since your update event is a new request to the server you shouldn’t save the previous context (context per request). You can use the Attach method of the ObjectContext with the ApplyCurrentValues (in EF4) or ApplyPropertyChanges (in EF1) in order to attach the entity and make is state as changed in order to commit an update.

    Reply
  9. EdmilsonJuly 17, 2010 ב 18:59

    Hi Gil,

    I´d like to know if is possible get lazyLoadind benefits from this aproach, I´ve been looking one way go get the one List or Collection of the related objects using the GetByID method but didn´t yet.

    []´s

    Edmilson

    Reply
  10. specterAugust 11, 2010 ב 15:28

    Hello, Thanks for your work. I’m working with Visual Studio 2008 and I’d like to know if this pattern will work on entity framework v1.

    Thanks in advance.

    Reply
  11. Gil FinkAugust 11, 2010 ב 16:03

    @specter,

    The code shown here is based on elements that are available in EF4 such as ObjectSet. You still can impose the repository and unit of work in EF1 but that will be harder.

    Reply
  12. DhaniAugust 20, 2010 ב 21:23

    Hi Gil,I read on some other post that instead of making Repository as part of UnitOfWork, they tend to make UnitOfWork as part of Repository. What is the design consideration about this ?

    Reply
  13. Gil FinkAugust 21, 2010 ב 13:33

    @Dhani,
    The Unit of Work pattern is defined as “Maintain a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems.” (taken from Martin Fawler’s book “Patterns of Enterprise Application Architecture”). The Repository is meant to be an abstraction layer above the data mapping layer (ADO, EF, LINQ to SQL etc). As I see it the unit of work which coordinate the business transactions will use repositories in order to do its work and not the opposite as you indicated.

    Reply
  14. Tomas F.August 31, 2010 ב 12:34

    Hi Gil,

    could you explain me please how to implement the above mentioned IContext interface with dependency injection  for example via IoC? Let’s say that:

     protected IObjectSet<T> _objectSet;

     public Repository(IContext context)

     {

       //_objectSet = context.CreateObjectSet<T>();

     }

    How to inject both ObjectContext : IContext and MockContext : IContext to the _objectSet variable through constructor injection? My problem is that MockContext doesn’t implement CreateObjectSet<T>(), but MockContext contains a private variable IObjectSet<Customer> _customers.

    Thank you for your advice, Tomas

    Reply