Why shouldn't I use the repository pattern with Entity Framework?

  • During a job interview, I was asked to explain why the repository pattern isn't a good pattern to work with ORMs like Entity Framework. Why is this the case?

    it was a trick question

    I would probably have answered to the interviewer that Microsoft use the repository pattern very often while they demonstrate the entity framework :| .

    So what was the interviewer's reason for it not being a good idea?

    The funny fact is that searching for "repository pattern" in Google gives the results which are mostly related to Entity Framework and how to use the pattern with EF.

    check ayende's blog http://ayende.com/blog. Base on what I know, he used to use Repository Pattern but eventually gave it up in favor of the Query Object Pattern

    The repository pattern is outdated. And causes lots of problems.

    I expect this is a question trying to get you to think about the downsides of generally good things. Everything has downsides

  • Shyju

    Shyju Correct answer

    8 years ago

    I don't see any reason for the Repository pattern to not work with Entity Framework. Repository pattern is an abstraction layer you put on your data access layer. Your data access layer can be anything from pure ADO.NET stored procedures to Entity Framework or an XML file.

    In large systems, where you have data coming from different sources (database/XML/web service), it is good to have an abstraction layer. The Repository pattern works well in this scenario. I do not believe that Entity Framework is enough abstraction to hide what goes on behind the scenes.

    I have used the Repository pattern with Entity Framework as my data access layer method and am yet to face a problem.

    Another advantage of abstracting the DbContext with a Repository is unit-testability. You can have your IRepository interface to which has 2 implementations, one (the real Repository) which uses DbContext to talk to the database and the second, FakeRepository which can return in-memory objects/mocked data. This makes your IRepository unit-testable, thus other parts of code which uses IRepository.

    public interface IRepository
    {
      IEnumerable<CustomerDto> GetCustomers();
    }
    public EFRepository : IRepository
    {
      private YourDbContext db;
      private EFRepository()
      {
        db = new YourDbContext();
      }
      public IEnumerable<CustomerDto> GetCustomers()
      {
        return db.Customers.Select(f=>new CustomerDto { Id=f.Id, Name =f.Name}).ToList();
      }
    }
    public MockRepository : IRepository
    {
      public IEnumerable<CustomerDto> GetCustomers()
      {
        // to do : return a mock list of Customers
        // Or you may even use a mocking framework like Moq
      }
    }
    

    Now using DI, you get the implementation

    public class SomeService
    {
      IRepository repo;
      public SomeService(IRepository repo)
      {
         this.repo = repo;
      }  
      public void SomeMethod()
      {
        //use this.repo as needed
      }    
    }
    

    I didn't said it will not work , I am also worked with repository pattern with EF , but today I was asked why IT IS NOT GOOD to use the pattern with DataBase , application that using Database

    Ok , since this is the most popular answer I'll chose it as Correct Answer

    When was the last time that most popular == correct?

    DbContext is already a repository, the repository is meant to be a low level abstraction. If you want to abstract different data sources create objects to represent those.

    There are many reasons not to use Repository pattern with OR Mappers. It's two years after this answer was given. Now you can find all of them easily on Google.

    I just wanted to add my perspective of how Entity Framework is not a repository

    But It is not possible to get migrations to work , as the connection string resides int he web.config. There is no way that migrations gets the connection string from web.config

    I've faced plenty of problems with the repository pattern. "Distributed transactions", "Connection Pool Exhaustion", "Partial Rollback" this all stems from trying to reuse multiple repository in the same transaction, since all the code lies there. Use UnitOfWork pattern or better yet skip this overabstraction nonsense and just create the DBContext and transactions in the Controller layer.

    ColacX. We tried just that--DBcontext right in the controller layer--and we are reverting to the repo pattern. With the Repo pattern, the Unit Tests went from massive DbContext mocking that constantly failed. EF was was difficult to use and brittle and cost hours of research for EF nuances. We now have small simple mocks of the repo. The code is cleaner. The separation of work is clearer. I no longer agree with the crowd that EF is already a repo pattern and already unit testable.

    @Shyju Can you refer a good article that mentioning of "Implement the Repository Pattern in an ASP NET MVC and WEB API" ?

    @ColacX I'd be curious of your thoughts now. I've found EF's dbcontext very easy to mock. I don't use EF directly in controllers but in a service layer instead as I treat it as a repo. Saves complexity, typing, readability, etc I find.

    yea. This answer was written a long time ago. But i tend to still wrap EF DbContext code behind an interface so that i can mock easily

    @user441521 I did not write my comment previous properly my apologies, I did not mean to put all the code into the Controller layer what I mean is that you instantiate the DbContext instance and/or transactions in the Controller layer. What I do then is to pass the reference down into the Service layer. This similar to the Repo pattern the difference is that the Repo pattern creates the DbContext in the Repo layer which causes all the problems mentioned previously. You can easily mock and unit test this Service Layer without problems.

    @ColacX You don't use a DI framework to get the DbContext to the Service and then to get the Service to your controller?

    @user441521 no the reason why is because the DbContext creates its own instance of a DbConnection. Thus when reusing the multiple services in the same request, it actually creates multiple connections which was not the intention. Worse is when you try to fix the problem by wrapping the whole request in one DbTransaction then the transaction becomes a distributed transaction, which again was not intended.

    @ColacX With Microsoft Unity DI framework, and I would assume most DI frameworks, you can control the lifespan of these objects. By default a new instance is created each time it's needed, but you can tell it not to do that and use the 1 instance (first instance acting like a singleton of sorts) with all subsequent requests to resolve. That way you get the same/shared instance between everything that needs it for said request.

    @user441521 that's true if people feel comfortable with using a request-life-time-cycle on their dependency injection. personally I feel that it is prone to hard detect bugs as one can easily inject the instances incorrectly. that being said one can say that repository pattern must be used with DI to function correctly. i still feel the repo pattern is outdated a stateless service is cleaner, easier and guarantees that you cannot get stuck in a "incorrect-middle-state".

    The real problem here lies in the "new DbContext" declaration in the Repository constructor. If you have multiple repositories that depend on each other you will get all sort of problems due to the fact that EF is meant to work with single context. Not to mention multithreading.

License under CC-BY-SA with attribution


Content dated before 6/26/2020 9:53 AM