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
69 comments
104230 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 the 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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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 +00: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...
#2383
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Tarik Guney on 03/07/12 5:53:54 Wednesday (UTC +00:00)
I've been thinking about the Individual repo interfaces after your Generic Abstract class. Do you still need them? You can put the GetSingle() method in abstract class and leave the implemention to the derived classes? IBarRepository and IFooRepository might be reluctant here? Or this is a must to follow the repository pattern?
#2385
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Tugberk on 03/07/12 10:40:54 Wednesday (UTC +00:00)
@Tarik The abstract class is generic. It saves you many keystrokes and you don't repeat yourself this way. But you might need different methods on different objects. That's the reason why we have individual interfaces and implementations of them.
#2399
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Fabuloes on 03/12/12 15:40:31 Monday (UTC +00:00)
Hi Tugberk,
Your generic repository depended by DbContext class doesnt it?,you must seperate them using unitofwork pattern? and you dont use any consructor which has parameter for DbContext, if you set generic type..
#2400
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Tugberk on 03/12/12 16:31:21 Monday (UTC +00:00)
@Fabuloes For now, yes. It depends on the DbContext class which is set as generic type. I have been thinking about that: should this implementation accept DbContext as constructor parameter or not?
#2430
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Eric on 03/19/12 16:14:02 Monday (UTC +00:00)
Hi and thank you for this post!
Everything works fine for me except transactions (using TransactionScope) when I insert data in multiple tables. If an exception occurs in the middle of my transaction, some data are persisted. Do you have any idea?
Thanks in advance.
#2446
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by mansi on 04/05/12 20:47:26 Thursday (UTC +00:00)
sir , wl u plz telmme where this coding has been done ?? i mean to say whether repositories are formed on class files or file of ny othr xtnsion...plz rply asap
#2457
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by AJ on 04/12/12 13:32:42 Thursday (UTC +00:00)
I just wondering if this supports transaction since it's creating DbContext each time an instance of Repository is being used?
#2461
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Mike on 04/18/12 10:37:09 Wednesday (UTC +00:00)
I'm using a winform to populate a gridview using the generic repository implementation. However, when I re-query to update the gridview, I get the old results minus any new records that have been added. I believe this has to do with the default MergeOption being set to AppendOnly and the entity I am re-querying already being in the ObjectContext. I'm wondering how/where I would introduce the MergeOption.OverwriteChanges into this pattern to force it to go to the database to get the results. Hopefully what I am asking makes sense, I'm still very new to Entity Framework. Thanks, Mike
#2462
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Mike on 04/18/12 11:10:13 Wednesday (UTC +00:00)
Found a solution to my above problem - "AsNoTracking()" returns a new query where the entities returned will not be cached in the DbContext or ObjectContext. public IQueryable<T> FindBy(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{ IQueryable<T> query = _entities.Set<T>().Where(predicate).AsNoTracking(); return query; }
#2508
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Nahuel on 05/15/12 21:31:25 Tuesday (UTC +00:00)
I have a question: Supose that Foo has a property of type Bar, and in the Foo Edit page, you have to fill it with an existing Bar, so you need some way to load all Bars to fill a combo in the Edit Foo page, to allow the user to select one Bar from the list. How would be the best way to do that?
#2522
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Sanjay on 06/02/12 7:22:09 Saturday (UTC +00:00)
I have read your atricle this is good but i have one confusion on [Ben Foster suggest] http://www.tugberkugurlu.com/archive/generic-repository-pattern-entity-framework-asp-net-mvc-and-unit-testing-triangle#2320. Can you tell me which one best approach?
#2532
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Joseph Morgan on 06/14/12 16:54:32 Thursday (UTC +00:00)
I found issues with using your code as written. I was getting InvalidCastException because my EF class was not a DBContext. So I rewrote your code (and used IEnumerable in place of IQueryable since I planned to use the outputs in tables and such and use for loops to present them in Razor)
Here is my generic repository and IGeneric Repository. Feel free to use them any way you like, as I built them from your example. I had to parse out the enitity set name because my EDMX is in a Models folder.
public interface IGenericRepository<T> where T : class { IEnumerable<T> SelectAll();
T SelectOne(Expression<Func<T, bool>> predicate);
IEnumerable<T> SelectWhere(Expression<Func<T, bool>> predicate);
void Add(T entity);
void Delete(T entity);
void Edit(T entity);
void Save(); }
public abstract class GenericRepository<C, T> : IGenericRepository<T> where T : class where C : ObjectContext, new() { private C db = new C();
public C Context { get { return db; } set { db = value; } }
public virtual IEnumerable<T> SelectAll() { IEnumerable<T> query = db.CreateObjectSet<T>(); return query; }
public virtual T SelectOne(System.Linq.Expressions.Expression<Func<T, bool>> predicate) { T entity = db.CreateObjectSet<T>().Where(predicate).FirstOrDefault<T>(); return entity; }
public IEnumerable<T> SelectWhere(System.Linq.Expressions.Expression<Func<T, bool>> predicate) { IQueryable<T> query = db.CreateObjectSet<T>().Where(predicate); return query; }
public virtual void Add(T entity) { string entityType = entity.GetType().ToString(); int start = entityType.LastIndexOf(".") + 1; string entityName = entityType.Substring(start, entityType.Length - start);
db.AddObject(String.Format("{0}.{1}s", db.DefaultContainerName, entityName), entity); }
public virtual void Delete(T entity) { db.DeleteObject(entity); }
public virtual void Edit(T entity) { db.ObjectStateManager.ChangeObjectState(entity, System.Data.EntityState.Modified); }
public virtual void Save() { db.SaveChanges(); } }
#2533
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Joseph Morgan on 06/14/12 17:10:56 Thursday (UTC +00:00)
I had to make some more tweaks, since there were attachment issues when I tested. I will post the code when I have tested the whole repository.
Joey
#2544
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Dhiren Naik on 06/29/12 7:52:11 Friday (UTC +00:00)
Good Post. I am new to Entity frame work. Very usefull to me. thanks.
#2547
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Stephen on 07/02/12 5:22:18 Monday (UTC +00:00)
Hi,
I am trying to use this and everything is good until i try using the "include" method and nothing happens. The following is what I am trying:
public IQueryable<T> FindByIncluding(Expression<Func<T, bool>> predicate, params string[] includeProperties) { IQueryable<T> query = _entities.Set<T>().AsExpandable().Where(predicate); foreach (var includeProperty in includeProperties) { query = query.Include(includeProperty); } return query; }
#2550
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Luis on 07/03/12 8:08:51 Tuesday (UTC +00:00)
Hello.
Do you have an example of YOUR generic repository and als othe unit of work pattern?
#2610
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Guy TALOM on 07/21/12 20:34:01 Saturday (UTC +00:00)
Hello !! Thank's for the simplicity and the quality of you article. I really apreciat he reusable benefit on th DRY when you creating an abstract class to server as base respository class. While triying to do it myselft, i got the idea to make all my Entity framework classe inherit from a Comme class called Identifiable. This class only focus on the capability of classes to have an Id(mapped to the corresponding unique Id in database). Since ia can identify every object with its Id, i canimplement a concrete method GetById() like this :
public T GetById(int id) { return this.Context.Set<T>().Single(p => p.ID == id); } And finally i just have one an generic Class GenericRepository to manage my domain model.
#2625
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Niels Brinch on 08/09/12 8:08:11 Thursday (UTC +00:00)
Thanks for a great post. I decided to let my GenericRepository implement IQueryable. That way I don't have to use "GetAll" or even "AsQueryable" when I use it, which makes for a bit sweeter syntax. I kept the AsQueryable as a private method like this:
private IQueryable<T> AsQueryable() { IQueryable<T> query = _entities.Set<T>(); return query; } Then implementing IQueryable was very easy - simply call the corresponding methods on the internal AsQueryable. public IEnumerator<T> GetEnumerator() { return AsQueryable().GetEnumerator(); }
#2628
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by divya on 08/17/12 2:22:01 Friday (UTC +00:00)
Hi, I have to say great explanation.
If you do consider my request, I would also like you to write articles on following topics since i strongly feel that through understanding of following terminology will greatly improve learning experience of this pattern. 1) Lambda Expression 2) Expression<T> 3) DataContext Class 4) IEnumerable 5) IEntity 6) IQueryable 7) LINQ
Thank you
#2678
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by bilgehan on 10/18/12 20:11:08 Thursday (UTC +00:00)
Hi,
Do you have repository pattern examples of using ASP.NET MVC + plain ADO.NET (no orm)?
#2688
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Bala on 10/25/12 13:07:23 Thursday (UTC +00:00)
Hi,
I am implementing Repository Pattern in one of my project based on ASP.NET MVC4 and N-Tier Architecture. I am little confused as how to implement Custom Membership with Repository Pattern. Here are how I have implemented my classes so far.
Generic Repository
public interface IRepository<T> where T : class { void Add(T entity); void Delete(T entity); void Update(T entity); IQueryable<T> GetAll(); T FindBy(Expression<Func<T, bool>> expression); IQueryable<T> FilterBy(Expression<Func<T, bool>> expression); }
Repository Base Class
public abstract class Repository<T> : IRepository<T> where T : class { private STNDataContext _stnDataContext; private readonly IDbSet<T> _dbSet;
protected Repository(IDatabaseFactory databaseFactory) { DatabaseFactory = databaseFactory; _dbSet = StnDataContext.Set<T>(); }
protected IDatabaseFactory DatabaseFactory { get; private set; } public STNDataContext StnDataContext { get { return _stnDataContext ?? (_stnDataContext = new STNDataContext()); } } public void Add(T entity) { _dbSet.Add(entity); _stnDataContext.Commit(); }
public void Delete(T entity) { _dbSet.Remove(entity); }
public void Update(T entity) { _dbSet.Attach(entity); _stnDataContext.Entry(entity).State = EntityState.Modified; _stnDataContext.Commit(); }
public IQueryable<T> GetAll() { return _dbSet.ToList().AsQueryable(); }
public T FindBy(Expression<Func<T, bool>> expression) { return FilterBy(expression).SingleOrDefault(); }
public IQueryable<T> FilterBy(Expression<Func<T, bool>> expression) { return GetAll().Where(expression).AsQueryable(); }
User Repository Interface
public interface IUserRepository : IRepository<User> { }
User Repository
public class UserRepository : Repository<User>, IUserRepository { public UserRepository(IDatabaseFactory databaseFactory) : base(databaseFactory) { } }
Heres my Business Logic Layer
Generic Service Interface
public interface IService<T> { void Add(T entity); void Delete(T entity); void Update(T entity); IEnumerable<T> GetAll(); T FindBy(Expression<Func<T, bool>> expression); IEnumerable<T> FilterBy(Expression<Func<T, bool>> expression); }
Service Base
public class Service<T> : IService<T> where T : class { public void Add(T entity) { throw new NotImplementedException(); }
public void Delete(T entity) { throw new NotImplementedException(); }
public void Update(T entity) { throw new NotImplementedException(); }
public IEnumerable<T> GetAll() { throw new NotImplementedException(); }
public T FindBy(Expression<Func<T, bool>> expression) { throw new NotImplementedException(); }
public IEnumerable<T> FilterBy(Expression<Func<T, bool>> expression) { throw new NotImplementedException(); } }
User Service Interface
public interface IUserService : IService<User> { }
User Service Implementation
public class UserService : Service<User>, IUserService { private readonly IUserRepository _userRepository; private readonly IRoleRepository _roleRepository;
public UserService(IUserRepository userRepository, IRoleRepository roleRepository) { _userRepository = userRepository; _roleRepository = roleRepository; }
public IList<User> GetAllUsers() { return _userRepository.GetAll().ToList(); }
public User GetUser(int id) { return _userRepository.FindBy(x => x.UserId == id); }
public User GetUser(string userName) { return _userRepository.FindBy(x => x.Username.Equals(userName)); }
public void CreatUser(User user) { _userRepository.Add(user); }
public IList<User> GetUsersForRole(string roleName) { return _userRepository.FilterBy(x => x.Role.RoleName.Equals(roleName)).ToList<User>(); }
public IList<User> GetUsersForRole(int roleId) { return _userRepository.FilterBy(x => x.Role.RoleId == roleId).ToList<User>(); }
public IList<User> GetUsersForRole(Role role) { return GetUsersForRole(role.RoleId); }
} Hi Bob, I am developing one application using ASP.NET MVC4, N-Tier Architecture and Repository Pattern. I want to implement Custom Membership functionality and refering your gpsnerd application as reference. I am little confused implementing the same. Can you help?
I am not very sure on Am I going the right way? If yes how do i implement my UserService class.
If no, what changes do i need to implement.
Any help on this is highly appreciable. Thanks in advance
#2690
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by rvl on 10/30/12 15:18:35 Tuesday (UTC +00:00)
Hi! Great article!
#2692
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Stefano on 11/05/12 10:40:59 Monday (UTC +00:00)
Hi there,
I implemented something similar, but I'm struggling where to put the code needed to increase the DbContext command timeout using Generic Repository. Couldn't figure how what to do. Any help will be very much appreciated! Thanks in advance,
Stefano
#2693
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Stefano on 11/05/12 10:43:41 Monday (UTC +00:00)
Let me add what I'd like to implement using generic repository:
I hope now it is more clear what I'd like to achieve. Thanks, Stefano
#2698
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Nagendra (Nags) on 11/07/12 19:26:07 Wednesday (UTC +00:00)
Hi Tugberk, first of all thanks for this great post.
I doownloaded code from following lnik https://github.com/tugberkugurlu/GenericRepoWebApp i ran project, but the Dispose method that you have discussed above is never called. do we have to call it explisitly by overriding the Dispose method of Controller, or it is called automatically after some condition which i do not know. please explain. i am going to use this pattern in my project the only thing which is not clear me is the above doubt.
#2699
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Nagendra (Nags) on 11/07/12 19:35:42 Wednesday (UTC +00:00)
Hi Tugberk,
hope you are doing great.
I have one doubt in above pattern. we are injecting the repository interface in controller right, now what if i want more than one repository in one controller. consider following case IFooRepository is injected by ninject in FooController. now for some reason i want to show list of all BAR elements in a dropdown in FOO Page, For this i need list of BARs in my FOOcontroller, to get list of Bars what is the best approach? as of now i am doing something like following.. barRepositorry objBarRepository=new barRepository() objBarRepository.GetAll()
so is it a proper way. or more then one repositories can be injected in one controller? offcourse in my above case if i create new objBarRepository....it will create new context.
#2702
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Jonathan Wood on 11/11/12 18:19:20 Sunday (UTC +00:00)
Being somewhat new to MVC (but not programming in general), I'm struggling with this a little. To me, it seems you've improved your code greatly by morphing it to a single version of your base class. But I still don't see why you need to then make concrete classes for each table. Why can't you have a true generic repository pattern that works something like this: var foos = repository.GetAll<Foo>(id); var bars = repository.GetAll<Bar>(id); This is what a repository does where I'm currently working. But it's very large and still a bit beyond my understanding. I need something simple for my own projects. But I'd prefer not to complicate my code with multiple repositories whose functionality may or may not overlap with other repositories.
#2727
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Emad Mokhtar on 12/13/12 6:55:05 Thursday (UTC +00:00)
Thanks for the great post and I've one question, Why not Save() method return int which is the number of rows afftected? Why void?
#2728
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by fandy on 12/15/12 13:37:23 Saturday (UTC +00:00)
Thanks for the great post. I am looking for the implementation of soft delete, would you have an idea on this using the generic repository.
#2809
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by Calvin W on 01/30/13 10:55:29 Wednesday (UTC +00:00)
Thanks for the post. I have a question about checking modification before perform update , is it possible ?, I tried to wrote some code but errro comes out and alert me have to Add or attach the entity before doing that..... world you please guide me the way ? Thanks !
public virtual void Edit(T entity) {
#2882
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by alirizaadiyahsi on 04/22/13 13:27:38 Monday (UTC +00:00)
Öncelikle elinize sağlık, bir sorum olacaktı; Sınıflara özel metodlar için nasıl bir tasarım tavsiye edersiniz. Örneğin, Role sınıfının kendine özel metodları var. Mesela, AddUserToRole, UserIsInRole, vs gibi. Bunları generic repository içerisinde tanımlayamayız, çünkü diger sınıfların bu metodlara ihtiyacı yok. Aslında ben hala Repository pattern, ORM araçları ile neden kullanılır anlamış değilim(Dependency Injection ile kullanımı hariç). Çünkü Entity Framework zaten UnitOfWork ve Repository Pattern kullanıyor. Benim öğrenmek istediğim, CRUD işlemleri haricindeki, sınıflara özel metodları nasıl tanımlamamız gerektiği. Bu konuda düşüncelerinizi paylaşırsanız sevinirim.
#2883
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by alirizaadiyahsi on 04/22/13 13:28:51 Monday (UTC +00:00)
Öncelikle elinize sağlık, bir sorum olacaktı; Sınıflara özel metodlar için nasıl bir tasarım tavsiye edersiniz. Örneğin, Role sınıfının kendine özel metodları var. Mesela, AddUserToRole, UserIsInRole, vs gibi. Bunları generic repository içerisinde tanımlayamayız, çünkü diger sınıfların bu metodlara ihtiyacı yok. Aslında ben hala Repository pattern, ORM araçları ile neden kullanılır anlamış değilim(Dependency Injection ile kullanımı hariç). Çünkü Entity Framework zaten UnitOfWork ve Repository Pattern kullanıyor. Benim öğrenmek istediğim, CRUD işlemleri haricindeki, sınıflara özel metodları nasıl tanımlamamız gerektiği. Bu konuda düşüncelerinizi paylaşırsanız sevinirim.
#2893
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by dakait on 05/09/13 4:57:23 Thursday (UTC +00:00)
hi Tugberk great post, can you please explain how can i implement the unit of work with your implementation
regards.
#2897
re: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle
by binjie on 05/17/13 18:30:06 Friday (UTC +00:00)
How about removing the type param from your interface but keep it in the methods signtures? public interface IGenericRepository { Then you only need one repository implementation for your entire data context and your implementation would effectively be entity agnostic, e.g.: var products = Rep.GetAll<Product>(); var customer = Rep.FindBy<Customer>(c=>c.Id = 123); Additional allowed tags : [quote]...[/quote], [user]...[/user]
|
Keep in Touch with MeTagsArchive
Blogroll |





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