Unit of work over Entity Framework

Many unit of work and repository implementations over Entity Framework do not respect the interfaces of the patterns correctly, and therefore the abstractions do not serve any purpose.

In my opinion, the single reason of abstracting unit of work and repository again, on top of Entity Framework’s database context and its entity sets should only serve one purpose: allowing changing the data access infrastructure (technology) in an application easier, i.e. without changing the application controllers (clients for data access layer) themselves. If you know that you’ll never need that, use the unit of work and repository pattern implementations already provided by Entity Framework itself!

In case you really need to abstract things again, start from re-reading and understanding the patters. Unit of work pattern should be defined in .NET using an interface like this:

public interface IUnitOfWork
  // Change notification methods.
  void RegisterNew(object entity);
  void RegisterDirty(object entity);
  void RegisterClean(object entity);
  void RegisterDeleted(object entity);
  // Commit and rollback methods.
  void Commit();
  void Rollback();

Have you ever seen such an interface implementing the unit of work pattern over Entity Framework this way? Probably you don’t find one on the Internet with ease. And this is because DbContext objects generated by Entity Framework are already good unit of work implementation themselves, as they have the powerful SaveChanges method and having automatic entity change management behavior in place offered through its IDbSet based repositories, and there is little interest to respect the true pattern. Also, some so-called repository implementations do not abstract the repository pattern over database entity sets away from database context, but are actually built on top of database context objects, which is, in my opinion, neither correct nor very useful.

From an architectural point of view I think we need to be able to change the data access technology from Entity framework to something else without modifying the application’s core. And we can avoid this unwanted dependency by respecting the pattern: in that case, we’d only need to implement the interface again using a different set of underlying services.

And what do we do when Register* methods get called? Well, who says we need to do anything?

  public void RegisterNew(object entity) { }
  public void RegisterDirty(object entity) { }
  public void RegisterClean(object entity) { }
  public void RegisterDeleted(object entity) { }

But we’ll do whatever needed when we’d implement the interface over a different technology, so the methods must exist.

Repository interface is easier to provide. We can rely on .NET core types such as IEnumerable<T> and Func<T, bool> to achieve what we need:

public interface IRepository<T>
  // Get methods.
  IEnumerable<T> GetAll();
  IEnumerable<T> Get(Func<T, bool> query);
  T GetSingle(Func<T, bool> selector);
  // Update methods.
  void Add(T item);
  void Remove(T item);

As you can see, this way unit of work and repository patterns are completely disjunct. None of them references the other. Many implementations found online will enforce a link, probably due to the way DbContext objects are generated by Entity Framework, including IDbSet<T> repositories for each model entity type as part that context. But that’s just specific for that one technology, and it’s not nice to have that link at generic level we want to abstract things out to.

Another concern is to be able to provide unit of work and repository implementations on top of Entity Framework (specific for that technology) that are still generic enough that it can be reused in different applications (for different database context instances, i.e. different entity models). This is possible indeed by simply adapting our pattern interfaces to Entity Framework’s core interfaces: IObjectContextAdapter and IDbSet<T>:

public class EntityFrameworkUnitOfWork : IUnitOfWork
  public EntityFrameworkUnitOfWork(IObjectContextAdapter objectContextAdapter)
public class EntityFrameworkRepository<T> : IRepository<T> where T: class
  public EntityFrameworkRepository(IDbSet<T> entities)

And now we’re ready for a client app (or, more often, client data access service). There we can either use EntityFrameworkRepository<T> class with specific entity types as type arguments or define custom repository classes if needed, inheriting from that base. Anyway we do it, the client code can then create its own DbContext as usual but then perform all data reading and writing through the unit of work and repository pattern implementations!

using (var sampleDbContext = new SampleDatabaseEntities())
  IUnitOfWork unitOfWork = new EntityFrameworkUnitOfWork(sampleDbContext);
  IRepository<Department> departmentRepository =
    new EntityFrameworkRepository<Department>(sampleDbContext.Departments);
  var developmentDepartment =
    departmentRepository.GetSingle(d => d.Name == "Development");
  var newDeveloper =
    new Employee {
      FirstName = "John", LastName = "Daniels",
      Department = developmentDepartment };

Of course, we can further abstract things and define an IDataAccessService interface and a generic EntityFrameworkDataAccessService<TDbContext> implementation to represent a factory for unit of work and repository instances for a specific database context type, and then the client side will simply use that one to get the references it needs for IUnitOfWork and IRepository<T>, but although that’s a great thing to do, it’s out of the scope of this discussion.

Maybe a diagram expresses the intended output even better:

Data access diagram
Feel free to use this approach in your applications whenever needed. I have managed to put the entire source code, including a small sample app, into a GitHub repository. Enjoy!

About Sorin Dolha

My passion is software development, but I also like physics.
This entry was posted in .NET, Architecture. Bookmark the permalink.

3 Responses to Unit of work over Entity Framework

  1. Tung Hoang says:

    Dear SDolha

    I used your framework update function using RegisterDirty not work. When updating the db is addnew.
    Tung Hoang


Add a reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s