15 Dec
2009

Entity Framework POCO (EF4): Generic Repository and Unit of Work Prototype

Category:UncategorizedTag: :

In my previous post I demonstrated how to create a simple mapping using the latest EF4 CTP. In this post I will look at how I can customize some infrastructure code in an attempt to align EF POCO “Code Only” with existing patterns, while potentially increasing reuse and testability.

A popular pattern for ORM data access is the Repository pattern. Implementing a generic repository in EF4 gets much easier with ObjectSet<T>. One might argue that it is, in a sense, a Repository.

What I would like to do is “Adapt” this interface to my own generic Repository. This will let me customize the interface to my own specifications and remove the dependency in my domain services on ObjectSet<T>.

Here is a great article based on the last CTP that does a nice job of laying out a Repository<T> strategy with a UnitOfWork, and here is another using nHibernate (see also UnitOfWork examples). If you are not familiar with the Generic Repository pattern and UnitOfWork, you should take a quick second and skim these before you continue. I want to take this implementation and try and change just a few things about it.

  • Static Unit of Work reference: First, I want to remove the Repository static reference to the UnitOfWork, which is how the Repository in the examples are resolving the ObjectContext/Session. Aside from not being a fan of static classes, I think it is the application Container’s responsibility to manage dependency resolution. Plus, I don’t really know that I want my Repository to have any reference to the UnitOfWork. I want the UnitOfWork to span across multiple repositories within a given transaction.
  • Object Lifetime: I would like to have more granular control over the UnitOfWork and ObjectContext lifetime. In the authors example, the UnitOfWork is managing the lifetime strategy, which is something the Container is perfect at handling. I will leave the UOW to transaction management only.
  • Constructor Injection: I think since the Repository has a hard dependency on the ObjectContext, that it would make the most sense to have the ObjectContext injected into Repository ctor.
  • Concrete ObjectContext reference: Since I will now be passing the ObjectContext into the ctor, I feel better if this was an interface. Not that I foresee a tremendous amount of testable value here, but I still don’t like taking a ctor dependency on a framework object if I can avoid it. Plus, this is prototype code, so why not?

Repository Interface

You will notice the interface remains unchanged from the first referenced article (Update: changed Func<T, bool> to Expression<Func<T, bool>> so that expressions can be evaluated correctly by ObjectQuery)

public interface IRepository<T> where T : class
{
    IQueryable<T> AsQueryable();
 
    IEnumerable<T> GetAll();
    IEnumerable<T> Find(Expression<Func<T, bool>> where);
    T Single(Expression<Func<T, bool>> where);
    T First(Expression<Func<T, bool>> where);
 
    void Delete(T entity);
    void Add(T entity);
    void Attach(T entity);

}

 

Generic Repository Implementation

As I described in the bullets above, my implementation does in fact take the IObjectContext as a ctor argument. Also, notice that I do not have any static references.

public class Repository<T> : IRepository<T> where T : class
{
   IObjectSet<T> _objectSet;
 
   public Repository(IObjectContext objectContext)
   {
       _objectSet = objectContext.CreateObjectSet<T>();
   }
 
   public IQueryable<T> AsQueryable()
   {
       return _objectSet;
   }
 
   public IEnumerable<T> GetAll()
   {
       return _objectSet.ToList();
   }
 
   public IEnumerable<T> Find(Expression<Func<T, bool>> where)
   {
       return _objectSet.Where(where);
   }
 
   public T Single(Expression<Func<T, bool>> where)
   {
       return _objectSet.Single(where);
   }
 
   public T First(Expression<Func<T, bool>> where)
   {
       return _objectSet.First(where);
   }
 
   public void Delete(T entity)
   {
       _objectSet.DeleteObject(entity);
   }
 
   public void Add(T entity)
   {
       _objectSet.AddObject(entity);
   }
 
   public void Attach(T entity)
   {
       _objectSet.Attach(entity);
   }

}

 

Unit of Work

Just like EF4 ObjectSet does a lot out of box for our Repository, the EF ObjectContext really does a lot of the work for us in regards to managing the UnitOfWork. The Object context is already capable of handling a transaction across many operations over different types. So, again, we are going to just add a little wrapper around the context and call it a UnitOfWork. This will give me a nice hook where my infrastructure can snag a reference to the ObjectContext and Commit the transaction changes, for example, at the end of a WCF, Web or DataService request.

interface IUnitOfWork
{
    void Commit();
}
 
public class UnitOfWork: IUnitOfWork, IDisposable
{
    private readonly IObjectContext _objectContext;
 
    public UnitOfWork(IObjectContext objectContext)
    {
        _objectContext = objectContext;
    }
 
    public void Dispose()
    {
        if (_objectContext != null)
        {
            _objectContext.Dispose();
        }
        GC.SuppressFinalize(this);
    }
 
    public void Commit()
    {
        _objectContext.SaveChanges();
    }
}

 

The Object Context Adapter

Just some Adapter 101 code here to abstract away the Concrete Context

public interface IObjectContext : IDisposable
{
    IObjectSet<T> CreateObjectSet<T>() where T : class;
    void SaveChanges();
}
 
public class ObjectContextAdapter : IObjectContext
{
    readonly ObjectContext _context;
 
    public ObjectContextAdapter(ObjectContext context)
    {
        _context = context;
    }
 
    public void Dispose()
    {
        _context.Dispose();
    }
 
    public IObjectSet<T> CreateObjectSet<T>() where T : class
    {
        return _context.CreateObjectSet<T>();
    }
 
    public void SaveChanges()
    {
        _context.SaveChanges();
    }
}

 

Using the Repository

Without out my application Container, here is how I would code up the new abstractions:

//...
// a bunch of ugly set up code here, see previous post
//...
 
var context = builder.Create(connection);
var contextAdapter = new ObjectContextAdapter(context);
var unitOfWork = new UnitOfWork(contextAdapter);
 
var teamRepository = new Repository<Team>(contextAdapter);
var newTeam = new Team { Name = "Da Bears" };
 
teamRepository.Add(newTeam);
unitOfWork.Commit();
 
var team = teamRepository.First(x => x.Name == "Da Bears");
Console.WriteLine(team.Name);
 
context.Dispose();

Admittedly, this is not very pretty and is still way more than I want to deal with on regular basis. In my next post I will demonstrate how I will tie all this together, EF Configuration, Repository and UnitOfWork using a Unity Extension.

Please keep in mind this is prototype, untested code on a CTP release. Code at your own risk!

29 thoughts on “Entity Framework POCO (EF4): Generic Repository and Unit of Work Prototype

  1. “Generic Repository Implementation

    As I described in the bullets above, my implementation does in fact take the IObjectContext as a ctor argument. Also, notice that I do not have any static references.”

    No it doesn’t, it takes in an ObjectContext.

  2. Btw, looking at this line:

    public class Repository : IRepository where T : class

    Since you already do:

    public interface IRepository where T : class

    is it required to have the where T : Class on Repository?

    I have no idea, just wondering if it is necessary.

  3. @jdn
    Yes you need at least the same restrictions on the implementation, they can be stricter I believe, but I don’t know how that works when using an interface that has where T : class, and the provided implementation has where T : class, new() since the user of the interface doesn’t expect that requirement.

  4. Oops, my mistake. I must have created an IObjectContext type in my project and forgot about it. I take back my previous comment.

  5. Nice start although I don’t think you want SaveChanges on the repository – it’s better on the unit of work as it saves everything in the context, not just the items for that repository.

    [)amien

  6. @Damien – Thanks. Removing SaveChanges() is a good idea, I hesitated leaving it on there.

    My test uses the UOW:
    teamRepository.Add(newTeam);
    unitOfWork.Commit();

    Getting rid of SaveChanges() would also allow me to remove the ObjectContext reference from the repository all together. Then use a Factory Func of some sort for _objectContext.CreateObjectSet() and have the DI container call it to satisfy the Repository ctor arg.

    I would also like to add the ability to shape the aggregate and define specifications using something like Includehttp://blogs.msdn.com/alexj/archive/2009/07/25/tip-28-how-to-implement-include-strategies.aspx

  7. English is not my native language, so I apologize for mistakes.
    Take a look at these two queries:

    var emps = from emp in repository.GetQuery()
    where emp.EmployeeID > 3
    select emp;

    var emps = repository.Find(e => e.EmployeeID > 3);

    when you start SQL Server profiler trace session, you can see that first one translates to something like this:

    “SELECT (allcolumns) FROM Employee WHERE EmployeeID > 3”

    while the second one translates to something like this

    “SELECT (allcolumns) FROM Employee” (without WHERE clause)

    Shouldn’t both queries translate to the same SQL query (the one with WHERE clause) ??

  8. @Nikola – Good catch. Single() & First() were broken too. I have updated the Repository impl to use an Expression as parameters instead of Func. ObjectQuery can now evaluate the expressions and generate the correct SQL.

    ———-
    * Since I was modifying the sample, I also removed SaveChanges() from the Repository as per Damiens suggestion (thus also removing the ObjectContext member var). Transaction should be managed only thru UOW now.

  9. Sorry if this is a lengthy comment.

    In your ObjectContextAdapter, you still have a Concerete constructor argument.

    public ObjectContextAdapter(ObjectContext context)

    which correct me if I am wrong, breaks the “ISP”.

    How about using something like this:

    interface IContextProvider {
    ObjectContext GetCurrentContext();
    // void SaveChanges(); // we can leave this to the UnitOfWork
    }

    and since EF4 provides partials, we could so something like this:

    public partial class (YOUR)ObjectContext : IContextProvider {
    public ObjectContext GetCurrentContext() {
    if(this.Connection == null)
    throw new ArgumentNullException(“Connection is null”);

    return this;
    }
    }

    What are your views/comments on this?

  10. EDIT: UnitOfWork can be modified to use IContextProvider objectContext as its argument instead of the IObjectContext objectContext argument.

    then using and IoC, the objectContext will auto-inject. if you know what I mean.

    – Great post by the way 🙂 thanks.

  11. EDIT: phew!
    The Repository can use IContextProvider too instead of IObjectContext.
    and you probably don’t need the CreateObjectSet() either altogether.

  12. why are you calling CreateObjectSet on every context so you can use it? this is a terrible design. So if I want to work with an POCO mapped to a table with 5 million rows, you are going to load all those rows into memory every time?

      1. Hi , I have a really silly question, 
        since I am newbie to, I wonder about this line : 
        “var context = builder.Create(connection);” 
        Is that just to instantiate the context ? 
        what is the type/class of “builder” ? 
        Is it a EntityConnectionStringBuilder Class as described in MSDN. 
        What I have seen in almost all tutorials till now is : 
        “var context = new MyModel()” 
        May be this is equivalent and the difference is that in the 2nd case   the model is often referenced from another ClassLib project. 

        Or may be they are different approaches and I am totally going in wrong direction.  

        Thanks for the explanation

  13. A common problem with methods that receive an Expression tree like Find, Single or First in your example is that they can not easily be mocked in an unit test with most of common Mocking frameworks out there. I can tell this from experience with previous developments.

  14. Hi

    Since Entity Framework 4.1 there is allready IObjectContextAdapter…Could we have used

        public class UnitOfWork : IUnitOfWork, IDisposable
        {
            private readonly ObjectContext _objectContext;

            public UnitOfWork(IObjectContextAdapter objectContextAdapter)
            {
                _objectContext = objectContextAdapter.ObjectContext;
            } //ommited for brevity }

    and

        public class Repository : IRepository where T : class
        {
            IObjectSet _objectSet;

            public Repository(IObjectContextAdapter objectContextAdapter)
            {
                _objectSet = objectContextAdapter.ObjectContext.CreateObjectSet();
            }

    //ommited for brevity }then usage becomes             var db = new MyEfCodeFirstContext();  // create context (could be auto wired I guess)

                var uow = new UnitOfWork(db);    // unit of workvar teamRepository = new Repository(db); // no adapter needed (EF provides one)
    var newTeam = new Team { Name = “Da Bears” };Thoughts?ThanksZ….

    1. Hi

      You mentioned that you are not keeping a static reference to unit of work…what if the user is work across multiple screens and getting and updating data within those screens?

  15. Hi, you can also add an (frequently used) order by function

    public IEnumerable GetAllOrderBy(Func keySelector) {
                return _objectSet.OrderBy(keySelector).ToList();
     }

  16. Hello, 

    1- 

    – i’m looking for “generic repository” and “generic unit of work” interface declerations and concrete implementation of these with EF.

    Since i want generic interface, the interfaces must not include anything specific to EF.

    Is IObjectSet specific to EF? If so, i think this interface is not generic enough. 

    2- I think the unit of work interface having just a “commit” function is not generic at all. It’s true just for your implementation logic…

    Just a Commit?  Let’s forget about repository(since it’s not mentioned in the interface). Is any concrete class implementing a simple commit function be UOW?  What will it commit???? Not generic or meaningful at all..

    The best UOW interface i’ve met so for is below. 

    If you can implement these with EF then it would be generic..

    Interfaces
    ————————————————————————
    public interface IAggregateRoot   
    {}

    public interface IUnitOfWorkRepository   
    {       
    void PersistCreationOf(IAggregateRoot entity);       
    void PersistUpdateOf(IAggregateRoot entity);       
    void PersistDeletionOf(IAggregateRoot entity);   
    }

    public interface IUnitOfWork
    {
    void RegisterAmended(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository);
    void RegisterNew(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository);
    void RegisterRemoved(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository);
    void Commit();
    }

    ————————————————————————Concrete UOW implementation ————————————————————————

    public class UnitOfWork : IUnitOfWork    
    {
    private Dictionary addedEntities;
    private Dictionary changedEntities;
    private Dictionary deletedEntities;

    public UnitOfWork()        {            addedEntities = new Dictionary();            changedEntities = new Dictionary();            deletedEntities = new Dictionary();        }        public void RegisterAmended(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository)        {            if (!changedEntities.ContainsKey(entity))            {                changedEntities.Add(entity, unitofWorkRepository);            }        }        public void RegisterNew(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository)        {            if (!addedEntities.ContainsKey(entity))            {                addedEntities.Add(entity, unitofWorkRepository);            };        }        public void RegisterRemoved(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository)        {            if (!deletedEntities.ContainsKey(entity))            {                deletedEntities.Add(entity, unitofWorkRepository);            }        }                public void Commit()        {            using (TransactionScope scope = new TransactionScope())            {                foreach (IAggregateRoot entity in this.addedEntities.Keys)                {                    this.addedEntities[entity].PersistCreationOf(entity);                }                foreach (IAggregateRoot entity in this.changedEntities.Keys)                {                    this.changedEntities[entity].PersistUpdateOf(entity);                }                foreach (IAggregateRoot entity in this.deletedEntities.Keys)                {                    this.deletedEntities[entity].PersistDeletionOf(entity);                }                scope.Complete();             }        }    }

    ————————————————————————

    These interfaces are from a book. Samples are freely available. The interfaces are in chapter 7 samples: 

    http://www.wrox.com/WileyCDA/WroxTitle/Professional-ASP-NET-Design-Patterns.productCd-0470292784,descCd-DOWNLOAD.html)

Comments are closed.

Find me

RSS
Facebook
Twitter
LinkedIn