Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
We will see how we can implement Generic Repository Pattern with Entity Framework and how to benefit from that.
12/22/2011 11:07:00 AM
35 comments
11351 times
DRY: Don’t repeat yourself which is a principle of software development aimed at reducing repetition of information of all kinds, especially useful in multi-tier architectures. That’s what Wikipedia says. In my words, if you are writing same code twice, follow these steps:
That’s what I have done for repository classes on my DAL projects. I nearly all the time use Entity Framework to reach out my database and I create repositories in order to query and manipulate data inside that database. There are some specific methods which I use for every single repository. As you can assume, those are FindBy, Add, Edit, Delete, Save. Let’s see on code what is my story here. First approach (worst approach) At first, long time ago, I have been creating all the single methods for each interface. For example below one is one of my repository interfaces:
public interface IFooRepository { IQueryable<Foo> GetAll(); Foo GetSingle(int fooId); IQueryable<Foo> FindBy(Expression<Func<Foo, bool>> predicate); void Add(Foo entity); void Delete(Foo entity); void Edit(Foo entity); void Save(); } This repo is for Foo class I have (imaginary). Let's see the implementation for Bar class. public interface IBarRepository { IQueryable<Bar> GetAll(); Bar GetSingle(int barId); IQueryable<Bar> FindBy(Expression<Func<Bar, bool>> predicate); void Add(Bar entity); void Delete(Bar entity); void Edit(Bar entity); void Save(); } Implementation nearly exactly the same here. Here is also an example of implementing one of these interfaces: public class FooRepository : IFooRepository { private readonly FooBarEntities context = new FooBarEntities(); public IQueryable<Foo> GetAll() { IQueryable<Foo> query = context.Foos; return query; } public Foo GetSingle(int fooId) { var query = this.GetAll().FirstOrDefault(x => x.FooId == fooId); return query; } public void Add(Foo entity) { context.Foos.Add(entity); } public void Delete(Foo entity) { context.Foos.Remove(entity); } public void Edit(Foo entity) { context.Entry<Foo>(entity).State = System.Data.EntityState.Modified; } public void Save() { context.SaveChanges(); } } Also imagine this implementation for BarRepository as well. Indeed, there would be probably more repository classes for your project. After playing like that for a while I decided to do something different which still sucked but better. A better approach but still sucks I created a generic interface which saves me a lot of keystrokes. Here how it looks like: public interface IGenericRepository<T> where T : class { IQueryable<T> GetAll(); IQueryable<T> FindBy(Expression<Func<T, bool>> predicate); void Add(T entity); void Delete(T entity); void Edit(T entity); void Save(); } And how I implemented in on repository interfaces: public interface IFooRepository : IGenericRepository<Foo> { Foo GetSingle(int fooId); } public interface IBarRepository : IGenericRepository<Bar> { Bar GetSingle(int barId); } You can see that I only needed to implement GetSingle method here and others come with IGenericRepositoy<T> interface. Where I implement these repository interfaces to my concrete classes, I still need to go over all the methods and create them individually. The repository class looked like as the same. So it leads me to a final solution which is the best one I can come up with so far. Best approach The generic interface I have created is still legitimate and usable here. In fact, I won’t touch the repository interfaces at all. What I did here first is to create an abstract class which implements IGenericReposity<T> interface but also accepts another type parameter defined in a generic declaration which is a type of DbConetxt class. Here is how it looks like: public abstract class GenericRepository<C, T> : IGenericRepository<T> where T : class where C : DbContext, new() { private C _entities = new C(); public C Context { get { return _entities; } set { _entities = value; } } public virtual IQueryable<T> GetAll() { IQueryable<T> query = _entities.Set<T>(); return query; } public IQueryable<T> FindBy(System.Linq.Expressions.Expression<Func<T, bool>> predicate) { IQueryable<T> query = _entities.Set<T>().Where(predicate); return query; } public virtual void Add(T entity) { _entities.Set<T>().Add(entity); } public virtual void Delete(T entity) { _entities.Set<T>().Remove(entity); } public virtual void Edit(T entity) { _entities.Entry(entity).State = System.Data.EntityState.Modified; } public virtual void Save() { _entities.SaveChanges(); } } This is so nice because of some factors I like:
So, when we need to implement these changes to our concrete repository classes, we will end up with following result: public class FooRepository : GenericRepository<FooBarEntities, Foo>, IFooRepository { public Foo GetSingle(int fooId) { var query = GetAll().FirstOrDefault(x => x.FooId == fooId); return query; } } public class BarReposiltory : GenericRepository<FooBarEntities, Bar>, IBarRepository { public Bar GetSingle(int barId) { var query = Context.Bars.FirstOrDefault(x => x.BarId == barId); return query; } } Very nice and clean. Inside BarRepository GetSingle method, as you see I use Context property of GenericRepository<C, T> abstract class to access an instance of DbContext. So, how the things work inside our ASP.NET MVC project? this is another story but no so complicated. I will continue right from here on my next post. UPDATE: Here is the next post: How to Work With Generic Repositories on ASP.NET MVC and Unit Testing Them By Mocking Comments
#2263
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Tugberk on 12/22/11 16:19:19 Thursday (UTC +02:00)
@ChrisMarisic Good catch. Actually, it wasn't there on my code but while I was writing the post, I wanted to add there. I don't know why but I like it to be there. As for your suggestion, yes it can be dropped and even as you suggested, we can have one method which accepts an optional paramater that is type of System.Linq.Expressions.Expression<Func<T, bool>.
#2264
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Chris Marisic on 12/22/11 16:42:47 Thursday (UTC +02:00)
Having the single queryable method makes mocking ridiculously easy. Using a similar interface, along with Machine.Specifications & Machine.Fakes.Moq List<Foo> FooRepository = new List<Foo> { ...... } The<IRepository<Foo>>() Nothing like being able to mock a database with a list. With a 2nd method you'd end up needing to basically duplicate the above mock but forward the where predicate to FooRepository.AsQueryable().Where(). Kinda lame to mock the same thing twice but only adding a .Where() to it.
#2275
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by GrahameSD on 12/23/11 19:05:36 Friday (UTC +02:00)
I had come up with a similar pattern in my own work and I followed a similar path to you. The main differences were that I was using an ObjectContext and I had to return IList<T> rather than IQueryable<T> due to architectural constraints. But I missed the FindBy with a predicate function - I'll have to start using that. One thing I'd suggest is to make the Context property in GenericRepository protected so that only the child repositories can get at it otherwise you defeat the object of encapsulating the DbContext. Anyway, great article. Keep 'em coming!
#2276
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Tugberk on 12/23/11 20:02:17 Friday (UTC +02:00)
@GrahameSD Your suggestion might be good. I must accept that I could be doing something against OOP here which I have no idea what they are. The one of the main reason I did the blog post is to get feedback like yours. Thanks!
#2277
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by denny on 12/24/11 18:22:22 Saturday (UTC +02:00)
Nice, but how to use a linq join to other tables!
#2278
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Tugberk on 12/24/11 18:56:07 Saturday (UTC +02:00)
@denny GenericRepository<C,T> abstract class exposes a public property named Context for your DbContext class. Use it to create other methods for your needs. Above, on the last code sample, I have an exmaple.
#2284
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by andyG on 12/29/11 18:27:04 Thursday (UTC +02:00)
Woudlnt you need to dispose the dbcontext? Im used to using the "Using" statement to make the connections, and im not seeing this being done... it may be my lack of experience in the EF, but i would assume you would need a way to dispose automagically... Does it need to be explicitly called?
#2285
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by andyG on 12/29/11 18:32:34 Thursday (UTC +02:00)
I may have answered my own question with more research. I guess it doesnt need to be explicitly called since the context doesnt hold open the connectiion... http://www.whitneyland.com/2008/06/linq-datacontex.html http://weblogs.asp.net/scottgu/archive/2007/08/16/linq-to-sql-part-6-retrieving-data-using-stored-procedures.aspx (see comment by scott gu near the bottom)
Thanks though... i do love this DRY method a lot...
#2286
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Tugberk on 12/29/11 21:53:24 Thursday (UTC +02:00)
@andyG yep, you are right. DbContext can be disposed. I actually implemented it on my github repo: https://github.com/tugberkugurlu/GenericRepoWebApp See the commit: https://github.com/tugberkugurlu/GenericRepoWebApp/commit/4a02be1ac1899a476c5f220e042dbbb65546e3cd
#2288
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Daniel on 12/30/11 16:08:44 Friday (UTC +02:00)
You would have some issues in the case that certain logic behaviors that are shared across multiple business classes, will use different repositories and, the same way, would use different contexts
#2292
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Tugberk on 12/30/11 18:51:40 Friday (UTC +02:00)
@Daniel Why will different contextes be used? Give an example. I didn't new up a new context instance inside the repository classes, It just uses the Context property.
#2294
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Chris on 01/06/12 23:53:38 Friday (UTC +02:00)
so here's my beef and I can't seem how to navigate this. Even when you use POCOs you're still coupled to some EF responsibilities. I want to be able to make model classes any ole way I want and persist them with EF (with some generic implementation if possible) or any other persistence model/device be it NHibernate, XML or simpleDb. Any suggestions?
#2297
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Myles on 01/09/12 19:03:42 Monday (UTC +02:00)
@Chris IGenericRepository is not specific to the EF. IGenericRepository would be defined in your Model somewhere. The EF project would define an implementation of IGenericRepository in the abstract class GenericRepository as was demonstrated above. If you needed to access any other data sources, you could build out your own implemenation of the IGenericRepository for that type of datasource, whether it be NHiberante, XML, or whatever. If the code you are writing to hit your repositories references the Interfaces and not the Implementations and using Dependency Injection it would be really simple to change from one implementation to another with a simple factory class or StructureMap etc... with very little effort.
#2303
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Peluca on 01/15/12 1:42:33 Sunday (UTC +02:00)
@Tugberk
Thank you for the nice generic Base Repo class. I have one question. Why did you not put the GetSingle method to the other generic methods in the base repo class? Just like this sample code:
public T GetSingleById(Expression<Func<T, bool>> predicateId) { var query = GetAll().Where(predicateId).FirstOrDefault(); return query; }
#2304
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Tugberk on 01/15/12 12:16:23 Sunday (UTC +02:00)
@Peluca That is actually right. It could work nicely but most of the cases, it is more convinient to pass the id of the current object to get the single value and I thought that I couldn't know inside the abstract class what the id of the object is, so I didn't do that. But your sample is great. I will implement that. BTW, you can fork me or open an issue if you want : https://github.com/tugberkugurlu/GenericRepository
#2305
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Peluca on 01/15/12 21:26:11 Sunday (UTC +02:00)
@Tugberk Well the reason why I suggested that because I wanted to avoid using another class which has to implement the IFooRepository or IBarRepository. I think if this repository is really a generic repository then it should be used like this within a ASP.NET MVC controller: public ActionResult Index(IGenericRepository repo) { var customers = repo.GetAll() // and all the other concrete methods from the GenericRepository class return View(customers); } I do not want the overhead of a FooRepository or BarRepository. I would also like to see or vote for it ;-) that you implement the the suggestion from Chris Marisic about the FindBy and GetAll().
#2306
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Tugberk on 01/15/12 22:29:47 Sunday (UTC +02:00)
@peluca I will include that as well but believe me, for a real word app you will definately find yourself implementing those repositories. On the other hand, if you don't implement concrete repo classes, you will need to mock the DbContext class on unit testing which will be hard to do. Check my other post on this and you will see what I mean: How to Work With Generic Repositories on ASP.NET MVC and Unit Testing Them By Mocking
#2307
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Peluca on 01/15/12 23:17:55 Sunday (UTC +02:00)
I do Unit tests on my mvc controller and integration tests for my repository including the business logic inbetween. So I do not need to mock the DbContext as I do not unit test my repository. Hope I got it right and understood you right. Thats an interesting link: http://stackoverflow.com/questions/6766478/unit-testing-dbcontext
#2308
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Peluca on 01/16/12 20:39:10 Monday (UTC +02:00)
@Tugberk
ah I see you already found it out :P
http://stackoverflow.com/questions/8623664/best-way-of-testing-repositories-which-use-dbcontext
#2309
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Peluca on 01/16/12 20:46:39 Monday (UTC +02:00)
@Tugberk
Still one thing came to my mind. Do you see any reason why not to include the save method
public virtual void Save() { _entities.SaveChanges(); }
into each Add/Delete/Edit repository method? That way I have not to call the Save explicitly and sometimes I could forget it...
#2310
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Tugberk on 01/17/12 12:19:59 Tuesday (UTC +02:00)
@peluca Yep, I look around a bit on how to unit test with directly consuming DbContext and the only way is to use a database only for testing. For your second suggestion, it is not a best practice to do that IMO, it is better act on this seperately.
#2311
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Ben on 01/18/12 12:08:41 Wednesday (UTC +02:00)
Thanks a lot for this article ! I have however changed something in your implementation. What I thought was bad in my implementation (your first approach) was not only the fact that there was a lot of code duplication but also that I was completly trashing the nice UnitOfWork pattern being DbContext. Indeed I was instanciating one DbContext PER repository, which is not (I think) a good thing. I had to run through a concrete problem to understand that. Everything was ok until a few days ago I had to do a complex linq query requiring doing an union on two DbSets (coming from two distinct repositories). I was thrown an ugly exception letting me know that no union was possible because unions needs to be done in the same DbContext (seems logical). I then realized that a single DbContext instance should be shared by all repositories, which is more than logical if you think about it, and correctly exposes the DbContext as a single UnitOfWork. So what I did is that I changed GenericRepository<C,T> as being only GenericRepository<T>. The concrete repository implementations are in charge of setting their GenericRepository dbContext upon creation (the dbContext instance is injected via NInject in concrete repository constructors, "InRequestScope"). To put it in a nutshell, here is what I got : ** ConcreteRepo ** Thanks again for your article.
#2312
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Tugberk on 01/18/12 13:55:50 Wednesday (UTC +02:00)
@Ben Nice comment! One thing I am wondering here is when EfGwConfigRepository comes in to play? Also, I would love to see the complate implementation, can you put it on github or somewhere else? Looks interesting and different.
#2313
The EfGwConfigRepository (one among many other concrete repository) just inherits from GenericRepository
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Ben on 01/18/12 19:54:53 Wednesday (UTC +02:00)
#2320
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Ben Foster on 01/21/12 12:01:55 Saturday (UTC +02:00)
I prefer to handle my unit of work (e.g. DbContext) outside of my repositories. In your example you are creating a DbContext per repository. Normally I prefer to have a DbContext-per-request that is shared by all repositories. I do this by abstracting DbContext into an interface and injecting this using a DI tool. Details on my post http://blogs.planetcloud.co.uk/mygreatdiscovery/post/EF-Code-First-Common-Practices.aspx
#2321
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Tugberk on 01/21/12 13:07:30 Saturday (UTC +02:00)
@BenFoster I'll read the article. Looks interesting and useful. What benefits does this give you by using a DbContext per request? Did you measure the perf?
#2336
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Lisa on 02/09/12 0:16:39 Thursday (UTC +02:00)
Hello Tugberk, Is it not that every time you create a FooRepository or BarRepository a new instance of type DbContext is created too? If yes, will there not be a problem with having multiple instances of the DbContext going out of sync?
Cheers, Lisa
#2337
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Tugberk on 02/09/12 11:24:30 Thursday (UTC +02:00)
@Lisa Yes, everytime you create a new repository instance, you will have a new DbContext instance, too. In fact, IMO, you should be working with this way. It prevents collisions. Here is a quoted sentence on this topic: The longer you hold onto the context, the more likely you are to get conflicts. Also, see my next post: How I use repositories is safe there. Also, @Ben has suggested another way above. He has a nice post on that as well. This is a really nice implementation of a repository. But I've been wondering if a repository is the best approach for making testable data access with the Entity Framework. I've heard some conflicting arguements that left me a bit confused. I blogged about them in this post: Do we need the repository pattern? I've also blogged about the alternative method I used: Mocking your Entity Framework data context and testing it in .NET MVC I'd be really interested to see what people think. I like my alternative and it's worked well for me, but I'd like to hear from anyone who knows what the pros and cons of both approaches are. [Peluca suggests](http://www.tugberkugurlu.com/archive/generic-repository-pattern-entity-framework-asp-net-mvc-and-unit-testing-triangle#2303) a GetSingle(...) method which takes in a predicate: Actually I think the proper approach is as Ben suggests to create a context-per-request, not per-repository. What if you need to interact with objects/queries across multiple repositories, as is often the case? Your unit of work object can keep track of the single context, and you can pass this from repository to repository. In fact, if you dispose of the context too soon and then create a new one, you will also run into conflicts ;-) Your generic repository can be modified very slightly to accept a context in its constructor:
private C _context; And then your unit of work, or whatever container class you want, can be in charge of passing the shared context into your various repositories.
#2342
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Tugberk on 02/11/12 22:32:30 Saturday (UTC +02:00)
@pandincus I really think that Ben's suggestion is a really good one and I really would like to put it as an option to this package. But in my personal opinion, if you need to interact with objects/queries across multiple repositories, there is probably something wrong with your domain model or repository implementation. Some of the project I have done earlier was like that and they all ended up dead because of the wrong implementation of repositories and domain model. Not to mention that it makes it hard to refactor your code.
#2343
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Matt C on 02/12/12 2:30:05 Sunday (UTC +02:00)
Good post. Definitely agree, per-request is best (actually, per-whatever is needed is best, depending on your implementation, so let the IoC implementation dictate) - the repository doesn't need to know about the persistence details, the unit of work takes care of that, including transactions, etc... Additional allowed tags : [quote]...[/quote], [user]...[/user]
|
Connect With MeTagsArchive
Blogroll |





Aren't GetAll & FindBy redundant?
Wouldn't it be clearer with a single "AsQueryable()" method or similar?