Generic Repository With EF 4.1 what is the point

As i dig deeper in to the DbContext, DbSet and associated interfaces, I am wondering why you would need to implement a separate "Generic" Repository around these implementations?

It looks like DbContext and IDbSet do everything you need and include the "Unit Of Work" inside DbContext.

Am I missing something here or does it seem people enjoy adding another layer of dependency for no reason.


Solution 1:

You are actually right. DbContext is an implementation of the unit of work pattern and IDbSet is an implementation of the repository pattern.

Repositories are currently very popular and overused. Everybody use them just because there are dozens of articles about creating repository for entity framework but nobody actually describes challenges related to this decision.

Main reasons for using repository are usually:

  • Hide EF from upper layer
  • Make code better testable

The first reason is some kind of architectonic purity and great idea that if you make your upper layers independent on EF you can later on switch to other persistence framework. How many times did you see such thing in the real world? This reason makes working with EF much harder because your repository must expose a lot of additional features wrapping what EF allows by default.

In the same time wrapping EF code can keep your code better organized and following Separation of concern rule. For me this can be the only real advantage of repository and unit of work but you have to understand that following this rule with EF will maybe make your code better maintainable and better readable but in the initial effort to create your application will be much higher and for smaller applications this can be unnecessary complexity.

The second reason is partially correct. The big disadvantage of EF is rigid architecture which can be hardly mocked so if you want to unit test upper layer you must wrap EF somehow to allow mocking its implementation. But this has many other consequences which I described here.

I follow Ayende's blog. If you ever used NHibernate you probably know his articles. This guy recently wrote several articles against using repository with NHibernate but NHibernate is much better mockable.

Solution 2:

I am struggling with the same issues, and mockability for unit testing of the EF layers is important. But I ran across this great article which explains how to set up the EF 4.1 DbContext to be mockable by making sure your derived DbContext implemented a generic interface and exposes IDbSet rather than DbSet's. Since I am using a Database First approach, because our database already exists, I simply modified the T4 templates used to generate my derived DbContext to generate it to return IDbSet interfaces, as well as derive from my generic interface. That way the entire thing can be easily mocked, and you don't need to implement your own Unit Of Work or repository pattern. Just write your service code to consume your generic interface, and when you go to unit test it, just mock the generic interface with specific test data and you are good to go.

http://refactorthis.wordpress.com/2011/05/31/mock-faking-dbcontext-in-entity-framework-4-1-with-a-generic-repository/