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.
2011-12-22 11:07
Tugberk Ugurlu


IMPORTANT NOTE:

I have a new blog post about Generic Repository implementation for Entity Framework. Please check it out instead of this one: Clean, Better, and Sexier Generic Repository Implementation for Entity Framework

NOTE:

Entity Framework DbContext Generic Repository Implementation Is Now On Nuget and GitHub: http://www.tugberkugurlu.com/archive/entity-framework-dbcontext-generic-repository-implementation-is-now-on-nuget-and-github

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:

  • Step back.
  • Sit.
  • Think about it and dwell on that.

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:

I am giving the examples here with EF 4.2 but I was following this approach with EF 4 which does not contain DbContext class.

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:

  • This implements so basic and ordinary methods
  • If necessary, those methods can be overridden because each method is virtual.
  • As we newed up the DbContext class here and expose it public with a public property, we have flexibility of extend the individual repositories for our needs.
  • As we only implement this abstract class only to our repository classes, it won’t effect unit testing at all. DbContext is not in the picture in terms of unit testing.

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

Chris Marisic
by Chris Marisic on Thursday, Dec 22 2011 16:08:16 +02:00

Aren't GetAll & FindBy redundant?

Wouldn't it be clearer with a single "AsQueryable()" method or similar?

Tugberk
by Tugberk on Thursday, Dec 22 2011 16:19:19 +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>.

Chris Marisic
by Chris Marisic on Thursday, Dec 22 2011 16:42:47 +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>>()
    .WhenToldTo(x => x.AsQueryable())
    .Return(FooRepository.AsQueryable());

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.

 

GrahameSD
by GrahameSD on Friday, Dec 23 2011 19:05:36 +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!

 

Tugberk
by Tugberk on Friday, Dec 23 2011 20:02:17 +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!

denny
by denny on Saturday, Dec 24 2011 18:22:22 +02:00

Nice, but how to use a linq join to other tables!

Tugberk
by Tugberk on Saturday, Dec 24 2011 18:56:07 +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.

andyG
by andyG on Thursday, Dec 29 2011 18:27:04 +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?

andyG
by andyG on Thursday, Dec 29 2011 18:32:34 +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...

Tugberk
by Tugberk on Thursday, Dec 29 2011 21:53:24 +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

Daniel
by Daniel on Friday, Dec 30 2011 16:08:44 +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

Tugberk
by Tugberk on Friday, Dec 30 2011 18:51:40 +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.

Chris
by Chris on Friday, Jan 06 2012 23:53:38 +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?

Myles
by Myles on Monday, Jan 09 2012 19:03:42 +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.

Peluca
by Peluca on Sunday, Jan 15 2012 01:42:33 +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;

        }

Tugberk
by Tugberk on Sunday, Jan 15 2012 12:16:23 +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

Peluca
by Peluca on Sunday, Jan 15 2012 21:26:11 +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().

Tugberk
by Tugberk on Sunday, Jan 15 2012 22:29:47 +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

Peluca
by Peluca on Sunday, Jan 15 2012 23:17:55 +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

Peluca
by Peluca on Monday, Jan 16 2012 20:39:10 +02:00
Peluca
by Peluca on Monday, Jan 16 2012 20:46:39 +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...

Tugberk
by Tugberk on Tuesday, Jan 17 2012 12:19:59 +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.

Ben
by Ben on Wednesday, Jan 18 2012 12:08:41 +02:00

Thanks a lot for this article !

My current implementation was exactly the one you used as First Approach (worst one) ... guess we read the same ASP.NET MVC book ;) I knew it was not the correct approach for my project and I was trying to find a way to refactor it. Your article greatly helped me through this.

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>.
I have exposed also exposed the inner DbContext in GenericRepository as a protected field (so that only concrete repository implementations have access to it, I really did not want the domain library user to have access to the context, too dangerous I think and what is the point of the repo in that case ;)).
My DbContext implementation also inherits from an interface called IDataContext which is just empty (solely used for injection purposes). 

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").

This way with only a few modifications, the dbContext is only known by the concrete Repositories (for extensions) and to the GenericRepository but not to the outside world, and most of all, the dbContext is shared by all the repositories during the request (UnitOfWork spirit).

To put it in a nutshell, here is what I got :

** IGenericRepository **
public interface IGenericRepository<T> : IDisposable where T : class

** EfGenericRepository **
public abstract class EfGenericRepository<T> : IGenericRepository<T> where T : class
{
/// The concrete implementation ***MUST*** set this context 
protected EfDbContext _efDbContext; 

** EfDbContext **
public class EfDbContext : DbContext, IDataContext

** IDataContext ** 
public interface IDataContext
{        

** ConcreteRepo **
// IDataContext is injected by NInject, InRequestScope
public EfGwConfigRepository(IDataContext context)
{
// Set GenericRepo context
_efDbContext =  context as EfDbContext;

** NInject config **
_ninjectKernel.Bind<IDataContext>().To<EfDbContext>().InRequestScope();

And that's it ;)

Please note that I'm far from being an expert in this field (or I wouldn't have implemented the worst approach in first place ;)), there may be better way to do this, but it worked fine for me and has the advantage of not complexifying the implementation.

Thanks again for your article. 

Tugberk
by Tugberk on Wednesday, Jan 18 2012 13:55:50 +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.

Ben Foster
by Ben Foster on Saturday, Jan 21 2012 12:01:55 +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 

Tugberk
by Tugberk on Saturday, Jan 21 2012 13:07:30 +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? 

Lisa
by Lisa on Thursday, Feb 09 2012 00:16:39 +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 

Tugberk
by Tugberk on Thursday, Feb 09 2012 11:24:30 +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: 

http://www.tugberkugurlu.com/archive/how-to-work-with-generic-repositories-on-asp-net-mvc-and-unit-testing-them-by-mocking

How I use repositories is safe there.

Also, @Ben has suggested another way above. He has a nice post on that as well.

Richard Garside
by Richard Garside on Thursday, Feb 09 2012 19:26:12 +02:00

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.

Richard Garside
by Richard Garside on Thursday, Feb 09 2012 19:30:01 +02:00

Just seen Ben's comment. Seems like he is using a similar method.

pandincus
by pandincus on Friday, Feb 10 2012 23:50:54 +02:00

[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:

    public T GetSingleById(Expression<Func<T, bool>> predicateId)
    {
        var query = GetAll().Where(predicateId).FirstOrDefault();
        return query;
    }

I like not having to implement the `GetSingle` method in all of my concrete repositories, but I don't like having to pass a predicate. However, can't we use the native `T DbSet<T> Find(params object[] keyValues)` method to take care of this for us?

> DbSet(Of TEntity).Find Method

> Uses the primary key value to attempt to find an entity tracked by the context. If the entity is not in the context then a query will be executed and evaluated against the data in the data source, and null is returned if the entity is not found in the context or in the data source. Note that the Find also returns entities that have been added to the context but have not yet been saved to the database.

So our implementation can be as simple as:

    public T GetById(int id)
    {
        return _context.Set<T>().Find(id);
    }
   
Granted this means we are constraining our method to accept an integer as the primary key, but that seems like a common enough situation to make this a feasible implementation.

pandincus
by pandincus on Saturday, Feb 11 2012 21:23:07 +02:00

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;

    public GenericRepository(C context)
    {
        _context = 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.

Tugberk
by Tugberk on Saturday, Feb 11 2012 22:32:30 +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.

Tarik Guney
by Tarik Guney on Wednesday, Mar 07 2012 05:53:54 +02: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?

Tugberk
by Tugberk on Wednesday, Mar 07 2012 10:40:54 +02: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.

Fabuloes
by Fabuloes on Monday, Mar 12 2012 15:40:31 +02: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..

Tugberk
by Tugberk on Monday, Mar 12 2012 16:31:21 +02: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? 

Eric
by Eric on Monday, Mar 19 2012 16:14:02 +02: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.

mansi
by mansi on Thursday, Apr 05 2012 20:47:26 +03: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
plz gv me a clr cut idea of repositroies also 

AJ
by AJ on Thursday, Apr 12 2012 13:32:42 +03:00

I just wondering if this supports transaction since it's creating DbContext each time an instance of Repository is being used?

Mike
by Mike on Wednesday, Apr 18 2012 10:37:09 +03: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

Mike
by Mike on Wednesday, Apr 18 2012 11:10:13 +03: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;

        }

 

Nahuel
by Nahuel on Tuesday, May 15 2012 21:31:25 +03: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?

Sanjay
by Sanjay on Saturday, Jun 02 2012 07:22:09 +03: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?

Joseph Morgan
by Joseph Morgan on Thursday, Jun 14 2012 16:54:32 +03: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();

        }

    }

Joseph Morgan
by Joseph Morgan on Thursday, Jun 14 2012 17:10:56 +03: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

Dhiren Naik
by Dhiren Naik on Friday, Jun 29 2012 07:52:11 +03:00

Good Post. I am new to Entity frame work. Very usefull to me.

thanks.

Stephen
by Stephen on Monday, Jul 02 2012 05:22:18 +03: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;
        }

Are you able to tell me why this is not working?
Luis
by Luis on Tuesday, Jul 03 2012 08:08:51 +03:00

Hello.

 

Do you have an example of YOUR generic repository and als othe unit of work pattern?

Guy TALOM
by Guy TALOM on Saturday, Jul 21 2012 20:34:01 +03: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.

 

Niels Brinch
by Niels Brinch on Thursday, Aug 09 2012 08:08:11 +03: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();

    }

 

divya
by divya on Friday, Aug 17 2012 02:22:01 +03: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

 

bilgehan
by bilgehan on Thursday, Oct 18 2012 20:11:08 +03:00

Hi,

 

Do you have repository pattern examples of using ASP.NET MVC + plain ADO.NET (no orm)?

Bala
by Bala on Thursday, Oct 25 2012 13:07:23 +03: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

rvl
by rvl on Tuesday, Oct 30 2012 15:18:35 +02:00

Hi! Great article!

I was wondering though: Why even after creating GenericRepository<C, T> you still had IFooRepository descend from IGenericRepository ?

Stefano
by Stefano on Monday, Nov 05 2012 10:40:59 +02: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

Stefano
by Stefano on Monday, Nov 05 2012 10:43:41 +02:00

Let me add what I'd like to implement using generic repository:

public class YourContext : DbContext
{
  public YourContext()
    : base("YourConnectionString")
  {
    // Get the ObjectContext related to this DbContext
    var objectContext = (this as IObjectContextAdapter).ObjectContext;

    // Sets the command timeout for all the commands
    objectContext.CommandTimeout = 120;
  }
}

 

I hope now it is more clear what I'd like to achieve.

Thanks,

Stefano

Nagendra (Nags)
by Nagendra (Nags) on Wednesday, Nov 07 2012 19:26:07 +02: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.

Nagendra (Nags)
by Nagendra (Nags) on Wednesday, Nov 07 2012 19:35:42 +02: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.

Emad Mokhtar
by Emad Mokhtar on Thursday, Dec 13 2012 06:55:05 +02: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?

fandy
by fandy on Saturday, Dec 15 2012 13:37:23 +02: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.

Calvin W
by Calvin W on Wednesday, Jan 30 2013 10:55:29 +02: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) {

if (CheckModified(this._entities.Entry(entity).OriginalValues, this._entities.Entry(entity).CurrentValues))
{
  _entities.Entry(entity).State = System.Data.EntityState.Modified; }
}

public bool CheckModified(DbPropertyValues originalValues, DbPropertyValues currentValues)
{

foreach (var o_propertyName in originalValues.PropertyNames)
{
foreach (var c_propertyName in currentValues.PropertyNames)
{
if (o_propertyName == c_propertyName)
{
if (originalValues[o_propertyName] != currentValues[c_propertyName])
{
return true;
}
}
}
}
return false;
}

alirizaadiyahsi
by alirizaadiyahsi on Monday, Apr 22 2013 13:27:38 +03: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.

 

alirizaadiyahsi
by alirizaadiyahsi on Monday, Apr 22 2013 13:28:51 +03: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.

 

dakait
by dakait on Thursday, May 09 2013 04:57:23 +03:00

hi Tugberk

great post, can you please explain how can i implement the unit of work with your implementation

 

regards.

binjie
by binjie on Friday, May 17 2013 18:30:06 +03:00

How about removing the type param from your interface but keep it in the methods signtures?

public interface IGenericRepository

{    
    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();
}

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);

johnson
by johnson on Wednesday, Jul 10 2013 08:23:42 +03:00
public class BarReposiltory : 
    GenericRepository<FooBarEntities, Bar>, IBarRepository  {

    public Bar GetSingle(int barId) {

        var query = Context.Bars.FirstOrDefault(x => x.BarId == barId);
        return query;
    }
}

i dont understand this bit especially FooBarEntities, where do the  FooBarEntities come from.
Steve W
by Steve W on Thursday, Aug 15 2013 20:45:42 +03:00

I used the pattern on this site. It worked perfectly up until I had two respositories open in the same controller post method (by design). Having a new DBContext for each repository became a problme for me. As nice as this pattern is, I have to unfortunately find another one because of this constraint.

Could you possibly modify it to use a shared context? I'd hate to have to start from scratch and I really liked it aside from the context problem.

Reuben Ahmed
by Reuben Ahmed on Sunday, Feb 02 2014 22:11:17 +00:00
Steve W, what about a Unit of Work approach? Typically this is used in conjunction with a Repository pattern.
serdar
by serdar on Saturday, Mar 29 2014 10:33:01 +00:00
Tugberk Bey elinize sağlık,süper bir anlatım olmuş
John
by John on Tuesday, Jun 10 2014 11:24:09 +00:00
Nice implementation. I have been using this and am struggling with inserting a graph of objects. Say you have Order and OrderItems classes. Consider the case where you are updating an existing Order and have added a few order items, modified others, and deleted a few. Additionally you have modified something in the Order entity itself. How would you accomplish that? jh
Daniel
by Daniel on Monday, Jun 30 2014 19:33:03 +00:00
In your GenericRepository, Don't you end up with a new instance of the dbContext for every repository by doing this: private C _entities = new C(); will all instances by in sync. Thanks.
Ibad
by Ibad on Sunday, Sep 28 2014 07:56:56 +00:00
Good Article! Can you please provide me the complete code in action? My email is baig.df@gmail.com Thanks.

New Comment