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?
-
72it was a trick question – Omu Dec 12 '12 at 21:34
-
3I would probably have answered to the interviewer that Microsoft use the repository pattern very often while they demonstrate the entity framework :| . – Laurent Bourgault-Roy Dec 28 '12 at 17:12
-
2So what was the interviewer's reason for it not being a good idea? – Bob Horn Dec 30 '12 at 15:42
-
4The 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. – Arseni Mourzenko Dec 31 '12 at 18:43
-
2check 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 – Jaime Sangcap Feb 02 '14 at 08:30
-
1The repository pattern is outdated. And causes lots of problems. – ColacX Jan 21 '16 at 10:16
-
I expect this is a question trying to get you to think about the downsides of generally good things. Everything has downsides – Richard Tingle Sep 07 '16 at 19:09
-
1**NOT good idea** `(UnitOfWork + Repository)` _by Rob Conery_ http://rob.conery.io/2014/03/04/repositories-and-unitofwork-are-not-a-good-idea/ – Kiquenet Mar 23 '17 at 12:55
-
Since the EF already implement the repository pattern, there is no clear benefit to add yet a repository abstraction on top. Probably they wanted to test if you understood the cost of adding unnecessary abstractions. – JacquesB May 21 '21 at 10:00
9 Answers
The single best reason to not use the repository pattern with Entity Framework? Entity Framework already implements a repository pattern. DbContext
is your UoW (Unit of Work) and each DbSet
is the repository. Implementing another layer on top of this is not only redundant, but makes maintenance harder.
People follow patterns without realizing the purpose of the pattern. In the case of the repository pattern, the purpose is to abstract away the low-level database querying logic. In the old days of actually writing SQL statements in your code, the repository pattern was a way to move that SQL out of individual methods scattered throughout your code base and localize it in one place. Having an ORM like Entity Framework, NHibernate, etc. is a replacement for this code abstraction, and as such, negates the need for the pattern.
However, it's not a bad idea to create an abstraction on top of your ORM, just not anything as complex as UoW/repostitory. I'd go with a service pattern, where you construct an API that your application can use without knowing or caring whether the data is coming from Entity Framework, NHibernate, or a Web API. This is much simpler, as you merely add methods to your service class to return the data your application needs. If you were writing a To-do app, for example, you might have a service call to return items that are due this week and have not been completed yet. All your app knows is that if it wants this information, it calls that method. Inside that method and in your service in general, you interact with Entity Framework or whatever else you're using. Then, if you later decide to switch ORMs or pull the info from a Web API, you only have to change the service and the rest of your code goes along happily, none the wiser.
It may sound like that's a potential argument for using the repository pattern, but the key difference here is that a service is a thinner layer and is geared towards returning fully-baked data, rather than something that you continue to query into, like with a repository.

- 6,374
- 3
- 14
- 13
-
95
-
This is something I have been wondering as well, as it was my thought too that the DbContext **is** the Unit of Work, so there's no need to create a layer above it that essentially just delegates back to an internal instance of DbContext. About the only reason I can see for having an abstraction layer is that you can't mock DbContext, so you have to rely on an actual database with data to do unit/integration testing. – Wayne Molina Jan 24 '14 at 15:01
-
14You *can* mock `DbContext` in EF6+ (see: http://msdn.microsoft.com/en-us/data/dn314429.aspx). Even in lesser versions, you can use a fake `DbContext`-like class with mocked `DbSet`s, since `DbSet` implements an iterface, `IDbSet`. – Chris Pratt Mar 06 '14 at 00:23
-
1this description sounds more like my idea of a repository layer. a wrapper that has methods that return and act on data entities. I guess my repos are pretty thin to begin with – TheZenker Mar 26 '14 at 12:10
-
16@TheZenker, you may not have been exactly following the repository pattern. The strictest difference is the return value. Repositories return queryables, whereas services should return enumerables. Even that's not really that black and white, as there's some overlap there. It's more in how you use it. A repository should just return the set of all objects, which you then further query into, while the service should return the final dataset, and should not support further querying. – Chris Pratt Mar 27 '14 at 14:31
-
2@ChrisPratt +1. The approach you suggest seems more reasonable than heaping abstractions upon abstractions. Can you point to any msdn example or other using EF that implements your suggested approach well from your perspective? – mg1075 Jul 19 '14 at 02:23
-
4@ChrisPratt but there are many tutorials on the web and official documentations from Microsoft that uses Repository and Generic Repository in their applications and examples. also one of the most populate asp.net mvc5 book named "Pro ASP.NET MVC 5" by Apress uses Repository pattern heavily... can you advice? – test test Oct 29 '14 at 16:13
-
14At the risk of sounding egotistical: they're wrong. Now, as far as the official tutorials go, Microsoft has backed off using repositories from what I've seen since EF6. Regarding the book, i can't speak to why the author chose to use repositories. What i can speak to, as someone in the trenches building large scale applications, is that using the repository pattern with Entity Framework is a maintenance nightmare. Once you move into anything more complex than a handful of repositories, you end up spending exhorbitant amounts of time managing your repositories/unit of work. – Chris Pratt Oct 29 '14 at 17:42
-
It's simply not worth the effort when you can get all the abstraction goodness with a much simpler and looser pattern such as services. – Chris Pratt Oct 29 '14 at 17:43
-
"People follow patterns without realizing the purpose of the pattern. In the case of the repository pattern, the purpose is to abstract away the low-level database querying logic." - then this answer is wrong and it contradicts itself, because EF queries are *database querying logic*. Granted is *nicely typed* and *automatically mapped*. – user2864740 Jan 05 '15 at 20:02
-
5@user2864740: First, notice the prefacing term "low-level". "The purpose of the repository pattern is to abstract away the *low-level* database querying logic." Second, EF syntax is *object-querying logic*. It may hit a database behind the scenes, but the same logic applies no matter what the data source is. – Chris Pratt Jan 05 '15 at 20:09
-
I think the repo/ef combo came from a desire to confine the "object-querying logic" behind methods on BL objects so that the entities would not become cross-cutting concerns. It gets redundant quickly for 2 reasons, though: 1) your queries generally end up returning Ixxxables anyway. You haven't simplified the object model and deferred execution still requires you to think though how you call the repository 2) say you require a repository layer to compose your complex entity object model, you're still either required to return those types from BL methods or create a whole new conceptual layer. – moarboilerplate Feb 04 '15 at 21:39
-
@user2864740 EF is not another fancy way of database querying, it is an ORM framework (http://en.wikipedia.org/wiki/Object-relational_mapping) designed to avoid the impedance mismatch (http://en.wikipedia.org/wiki/Object-relational_impedance_mismatch). – romanoza Apr 30 '15 at 17:33
-
The 'abstraction on top of your ORM' you are looking for is the Query/Command pattern this avoids all the maintenance issues and dependency hell. – DalSoft Jun 10 '15 at 10:45
-
I don't get this answer. If you write lots of linq queries against a DbContext, how on earth do you want to replace EntityFramework with something else without changing all those queries? If there was an abstraction on the DbContext level, that would be possible. – John Jul 07 '15 at 14:31
-
3You of course have to change the service. But, what I'm talking about is having stuff like `service.GetPublishedBlogPosts()` in your controller actions. Then, if you want to switch to something like Web Api, you just have to alter that method, not every single call to it throughout your application. It's even easier if you use interfaces and dependency injection, as then you can just drop in a brand new service implementation and you're off to the races. You *can't* do this using repositories, since they don't return fully-baked data. – Chris Pratt Jul 07 '15 at 14:58
-
1I want to embrace this philosophy, but I have one question: do you ever make more than one service? If so, how do you handle the case where a controller method might need to mutate the data contained within multiple services (e.g. `blogService.updatePost(...)` and `historyService.addEvent(...)`)? You lose the atomicity gained from the UoW pattern. Otherwise, if you don't create multiple services, doesn't your service become an unwieldy god class? – Pakman Jul 13 '15 at 02:42
-
7I usually have just one service per database or access method. I use generic methods to query multiple entity types from the same set of methods. I use Ninject to inject my context into my service and then my service into my controllers so everything is neat and tidy. – Chris Pratt Jul 13 '15 at 14:42
-
1The use of "generic methods to query multiple entity types" sounds like a generic repository, though. Don't you need non-generic methods like `GetPublishedBlogPosts`, `GetPublishedBlogPostsOrderedByDate`, `GetNonPublishedBlogPosts`, etc...? Otherwise, aren't you using LINQ-to-object in your controllers and losing the benefit of IQueryable repositories? – Pakman Jul 13 '15 at 16:18
-
4Not really, because I'm also employing interfaces, so I can have a method like `GetPublished
() where TEntity : IPublishable`. Sometimes I do tack on more specific methods via a partial class, though. – Chris Pratt Jul 13 '15 at 17:06 -
2I think this statement that Chris made is a bit misleading, and while not incorrect is somewhat counter productive. What a repository "should" be and the mistakes many people make are usually far from each other in most implementations. In other words don't judge the pattern by poor implementation. – Brandon Mar 13 '16 at 14:04
-
2What a repository should be with EF is nothing but a generic shell over the top of the DbContext, providing very simple methods for querying. No business logic, no custom queries, nothing. Just pure simple abstraction, for dependency injection mainly, and for a reusable interface. It helps with testing in the rest of the system, but shouldn't require unit testing itself. People just have a tendency to make it do too much, they let business concerns and poor judgement leak into their abstraction. Should be kept simple. Then I believe it can be very useful and make for a more stable system. – Brandon Mar 13 '16 at 14:05
-
There's no need for even that. EF6+ is 100% testable, and even prior versions implemented IDbSet for entity sets. You just couldn't mock the context, itself, but that hardly mattered. There's absolutely no reason to wrap anything around Entity Framework, except and unless, you're going to abstract away all the querying logic as well. – Chris Pratt Mar 14 '16 at 12:44
-
What is, if I need to switch some Linq Queries into stored procedures, like [mentioned here](http://stackoverflow.com/a/9739440/2441442). Would I call the stored procedure from the same service class? – Christian Gollhardt May 07 '16 at 00:13
-
Either that, or you can create methods on your context. I prefer to use the service class, though, so I can keep the context fairly agnostic. – Chris Pratt May 09 '16 at 13:50
-
1It seams that new Entity Framework Core does not have IDbSet interface and if you need to switch for example from EntityFramework to call to Webservices you will need to implement IQuerable for Linq queries as well. No thanks. I vote for Repository. – Radenko Zec Jun 14 '16 at 08:24
-
EF Core is still very much in development. I wouldn't base anything on what's happening there at this point. – Chris Pratt Jun 16 '16 at 12:51
-
1Based on recommendations, I implemented my code without the repository pattern, just using EF. I successfully mocked my Repository pattern as follows: http://www.rhyous.com/2015/04/10/how-to-mock-an-entity-framework-dbcontext-and-its-dbset-properties/ I fully regret it and am now moving it all back to the repository pattern. – Rhyous Jul 11 '16 at 22:45
-
4EF has proven to NOT already be a repository, but instead it is just a way to replace sql strings with statically typed code. In the end, not using the repository pattern has led to messy method code and overly complex Unit Tests. – Rhyous Jul 11 '16 at 22:50
-
1@ChrisPratt you say 'Entity Framework already implements a repository pattern' but i see many people to implement repository model in EF-Code first?even there are article about it : http://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application – AminM Aug 09 '16 at 10:13
-
@Rhyous: "just a way to replace sql string with statically typed code". That's the very definition of a repository. I'm not sure what you *think* a repository is supposed to do, but that's it. Hence why it makes no sense to wrap a repository around EF. Now, if you're talking about factoring out the actual querying logic, so you don't have Linq-to-Entities code in your actions, you're no longer talking about a repository, but something like a service or command-query pattern. – Chris Pratt Aug 15 '16 at 14:02
-
@Rhyous: Also not sure what the difficulty is in mocking EF. Time was that DbContext didn't implement an interface, but DbContext, itself, doesn't do much anyways. All the real work happens in DbSet, which has always implemented an interface that you could mock. However, DbContext now also implements an interface, so it should be a trivial matter to mock it. – Chris Pratt Aug 15 '16 at 14:04
-
5@AminM: It's the lemming phenomenon. Microsoft posted a highly ill-advised article back in like 2013. Inevitably, most new MVC devs stumbled upon this article (myself included) and, since it was from Microsoft, considered it carried the weight of best practice. Rinse and repeat for the last 3 years. However, any amount of serious app development will quickly teach you that that approach is folly. – Chris Pratt Aug 15 '16 at 14:08
-
2I can mock EF: http://www.rhyous.com/2015/04/10/how-to-mock-an-entity-framework-dbcontext-and-its-dbset-properties. The mock just didn't stand up in actual use. Then again, EF itself didn't stand up to production use without additional add-ons, such as LinqKit to fill in expected functionality that is missing. For the majority of Unit Tests, EF mocking worked all right. But the complexity increases whenever an extension method was called. EF often throws generic meaningless errors that didn't always work. Unit Tests passed but EF crashed. So we couldn't trust our unit tests. – Rhyous Aug 15 '16 at 14:54
-
2Also, the unit test complexity is greatly increased by mocking EF vs mocking a repository pattern. With the repository pattern, the unit tests are simple and straight forward, few lines of code, and fast to write. With EF, the unit tests were often complex, needing dozens of dbsets mocked just to run one test. It became clear that to Keep it Super Simple, using EF as a repository, while doable, wasn't the best choice. – Rhyous Aug 15 '16 at 14:56
-
@Rhyous: That's more of an indictment against EF as an ORM, in general, not as a "repository". It implements the repository pattern, and therefore it makes no sense to add another repository around it, but indeed there are many valid complaints to be made against EF. – Chris Pratt Aug 15 '16 at 15:29
-
1@ChrisPratt You are probably exactly right. I will agree that it is a repository pattern, but has complexities and difficulties. Quote from http://www.dofactory.com/net/facade-design-pattern: "Provide a unified interface to a set of interfaces in a subsystem. Façade defines a higher-level interface that makes the subsystem easier to use." Based on that quote, I am claiming that EF is a complex subsystem and to make EF easier to use and test, use the repository pattern as a facade to make the subsystem easier to use. – Rhyous Aug 15 '16 at 17:16
-
@Rhyous: I missed your last comment until just now, but EF is not a "complex subsystem". The exposed API is actually *extremely* simple. Sure, there's a ton going on under the hood, but that's already abstracted. I'm hard pressed to see how a repository wrapped around the public EF API somehow simplifies anything. – Chris Pratt May 01 '17 at 13:33
-
I have think about ASP.NET MVC with ViewModel / Service / Repo since I start project by MVC 3.0. Finally I withdraw the Repo layer, but keep Service layer call EF CRUD operation and return ViewModel to View. As same as @Chris Pratt said, the EF already did Unit of Work. However, I can't say I am correct because I having any unit test project. But without Repo, everything works and easy to maintenance. – Cheung Jun 15 '17 at 17:40
-
1I have been wondering the same thing and reading this lengthy discussion there is one thing I just can't get my head around: I agree that the low-level way of accessing data (i.e. translating LINQ expressions to SQL) should be hidden but I just can't understand why some people believe that the actual framework being used to use IQueryable
s should be hidden. I mean, they say "so you can swap out EF for RESTful calls or NHibernate" or whatever.... – Balázs Jun 24 '17 at 10:49 -
1... But: 1) are you really ever gonna do that? 2) Are you sure it will just "work"? I mean, how do you want to do LINQ queries on objects returned by a remote service? 3) This is the main concern: what do you gain by hiding the actual framework doing the work itself? For example, each and every framework has some feature that differentiates it from the others. By constructing a "common abstraction" of them all, you inevitably end up having access to only the common set of functionalities which is incredibly limiting... – Balázs Jun 24 '17 at 10:51
-
1... For example, EF has an extension `AsNoTracking()`. The last time I used NHibernate was really long ago but I cannot remember it had something like that. So, the unique features and methods, etc., are meant to be used but if you are going for a common abstraction layer you either: a) define that method but only one implementation will actually allow to use it (so what's the gain?) b) you opt to the common functionality set, losing all the good stuff provided by the framework which is absolutely pointless... – Balázs Jun 24 '17 at 10:53
-
... So how do you approach this particular issue, especially those who state that UoW/Repo should be implemented on top of EF? – Balázs Jun 24 '17 at 10:54
-
@Chris Pratt So ***if*** development time is not an issue, ***the ultimate "purist"*** solution could be: Use the `Repository Pattern/Unit of Work` to abstract a system to get `IQueryables` (You can implement it with Entity Framework or whatever), then abstract a `Service` on top of it which returns `IEnumerables`. With this approach, everything is based on abstractions, and the `business logic` will only consume the `IService`'s `IEnumerables` as-is, so there wont be 10-line LINQ's in the business logic here and there. `Business Logic` depends on `IService` depends on `IRepository`. Correct? – Sharky Jun 26 '17 at 08:21
-
3@Sharky: Not sure I understand where you're coming from. It really has nothing to do with dev time one way or another, and "purist" is kind of meaningless. There is no one right way to do anything in programming; only what works for a particular application in context. Simply, the repository pattern is never right unless you're dealing with low-level SQL: ADO.NET, Dapper, etc. If you're using an ORM like EF, it's 100% a waste of time and only increases the entropy of your code. A service layer is a good approach because it shuffles the LINQ-to-Entities code out of your app. Plain and simple. – Chris Pratt Jun 27 '17 at 02:31
-
1@ChrisPratt Don't you bother that your Services will be dependent on the ORM? Because `GetCustomersWhichHaveNotConfirmedTheirEmail` must use an EF dbContext. Woops, dbContext in Service?Why Service carries implementation details of data-access? A reason could be "we had no time to create/maintain the ORM behind a repository" (hence my prev comment). Instead if you had abstracted the ORM as a Repository sitting behind the service, service's `GetCustomersWhichHaveNotConfirmedTheirEmail` would just use a ICustomerRepository.Get(whatever-LINQ-LOGIC) and would be ORM-agnostic=clean architecture – Sharky Jun 27 '17 at 06:36
-
2Then the repository has the dependency. What's the difference. All you've done is add an additional layer you have to maintain. The point is to abstract the dependency from the application layer. A service layer is inherently tied to a data source, so it doesn't matter if that accesses the context directly. If your service implements an interface (as it should) then the provider pattern can be employed to switch out the data layer simply by creating a new service implementation and injecting that instead. – Chris Pratt Jun 27 '17 at 06:59
-
1It's not a matter of neglecting to take the time to set up a repository. The repository approach is *wrong*. Why devote development time to something that buys you nothing but technical debt. – Chris Pratt Jun 27 '17 at 07:01
-
1@ChrisPratt Thanks so much for this and your blog posts, "A Truly Generic Repository, Part [1-2]" (https://cpratt.co/truly-generic-repository/ , c. May 2016)...this comment train has rolled along since 2013, but these comments from June 2017 seem to indicate you've moved on from these blog posts...or am I misreading (?) Thank you. – iokevins Sep 05 '17 at 23:43
-
So Whats your final conclusion to not use repository pattern with `EF` ? If yes , then how would you do `DI` and what if you want to use `Oracle` as data source , see [this](https://stackoverflow.com/questions/10616131/repository-pattern-why-exactly-do-we-need-interfaces) post from @Darin Dimitrov which uses repository pattern to switch to different data source using `DI`. – Shaiju T May 09 '18 at 08:34
-
@stom: Data source has nothing to do with something like a repository. You inject your EF context. The actual provider is controlled elsewhere (i.e. Startup.cs in ASP.NET Core) and your connection string should likewise be abstracted outside of your context. Your context should not care what the underlying data source is, nor should something like a controller you're injecting that context into. – Chris Pratt May 09 '18 at 15:13
-
1Such a sensible answer - service classes with methods that apply to your domain (with DI), instead of trying to be super generic and adding layers of abstraction for no reason. In my experience you also end up losing much of the power of DbContexts rich querying capabilities and for what? – Michael Harper Aug 25 '18 at 09:14
-
@ChrisPratt +1 for answer, i'm doing my designs just like the way you mentioned and that's really easy and time-saver! who builds a UoW and Rep on something that already has both? – Amir Oveisi Nov 16 '18 at 16:18
-
@ChrisPratt but microsoft implement EntityStore for UserManager calss that seems implement RepositoryPattern and internally use DBset(EF implemention of RP,is there any reason??https://github.com/aspnet/AspNetIdentity/blob/master/src/Microsoft.AspNet.Identity.EntityFramework/EntityStore.cs – AminM Feb 21 '19 at 16:13
-
Yes. Identity is intentionally backend agnostic. They're building something that has be used by millions of different developers and millions of different applications on multiple platforms. That level of necessary abstraction counters the maintenance headache of the extra layer. That's not your situation. At best, you want to simply abstract away your data dependency and there's far better ways to do that, if that's your goal. Virtually every repository layer over EF is naive and doesn't actually abstract the dependency anyways. – Chris Pratt Feb 21 '19 at 17:21
-
3@ChrisPratt thanks for your continued effort to continue this thread! Do you have (or know of) any examples on GitHub et al that shows the use of Services instead of Repositories as you like to use in practice? – JTech Feb 22 '19 at 01:27
-
1Honestly, I've moved to microservice architecture now, and I use EF directly in those. Just works better and my app has complete data layer abstraction. – Chris Pratt Feb 22 '19 at 09:05
-
@ChrisPratt, in your answer, do you intend for the service implementation to manage the `DbContext`? If so, are cross-service `TransactionScopes` still a possibility? (I understand that you _could_ wrap those in such a service as well, but that limits our options, and I have some situations where it is undesirable.) – Timo Mar 18 '19 at 12:01
-
Services should be self-contained units. Since I originally wrote this answer, microservice architecture has become the new vogue, but even if your services are just classes in your code, you can and should still borrow from the principles of microservices. Namely, each spans a particular subdomain of your application. You can handle transactions within that subdomain, but anything outside should rely on a different strategy. What's contained in the subdomain of the service should be completely independent. – Chris Pratt Mar 18 '19 at 12:43
-
@ChrisPratt chris so you're basically saying, each for its own, each class instantiate its own dbcontext ? independent from the rest of your microservices / classes – Stavm Jun 24 '19 at 13:54
-
So true, don't waste time in writing code, dbcontext is our repository. Plus this is the main advantage of using an ORM – Luther May 27 '20 at 15:22
-
Hi @ChrisPratt. I've been trying very hard to buy this argument for the past few days, particularly since I'm using EF Core, and even more so after reading your [2018 article](https://cpratt.co/repositories-and-entity-framework/). However, one thing I can't seem to wrap my head around is: by using EF Core directly in the Services layer (which acts like an API for my application to consume), I will be writing data querying logic at the API level. Suppose I _do_ wish to isolate those in a Data Persistence layer: is there a "cleaner" way, or am I doomed to implement a repository pattern? – Marc.2377 Feb 01 '21 at 07:13
-
(...) not a generic repository, however, since as I understand it those do nothing more than proxy EF logic and it's kinda stupid. I simply don't want my Application Services layer to know or care whether some data is coming through EF Core, Dapper, or whatever else. P.S.: When answering my comment, keep in mind I can't/won't be converting my projects to the microservices architecture. I thank you for all of your insights. – Marc.2377 Feb 01 '21 at 07:16
-
When you use an ORM like EF, *that* is your DAL. You've just opted to use one created by third party, rather than yourself. If you're doing something like using ADO.NET directly, then creating a separate DAL would be appropriate, if redundant, as there are things like EF available. If you want abstraction beyond that, you can opt for the service layer pattern, CQRS, or microservices. Otherwise, use EF or whatever directly. Essentially, your application is either complex or it isn't. If it's not, trying to abstract.a dependency a DAL is not worthwhile. – Chris Pratt Feb 01 '21 at 12:40
-
1I'm curious where you heard/decided that a Repository must return a Queryable (mentioned in comments above)? I've been using the Repository pattern for years and returning IQueryable from a Repository leaks all kinds of implementation details and so *that* is an antipattern, not the use of the Repository at all. When you use a Repository *abstraction* in your domain model (it's a DDD pattern, after all), you get the benefit of constraining how you expect to manage persistence in your model. EF (Core) is an implementation detail, not an abstraction, so isn't part of a domain model. – ssmith Apr 20 '21 at 18:25
-
1@ssmith Yeah, I'm curious as well. Repositories, as defined by Fowler in P of EAA, accept object-oriented criteria (as opposed to say SQL) and return domain objects. The pattern predates Entity Framework and most ORMs by years (and therefore queryables). In addition, it seems that these days, people mainly talk about repositories as a means of abstracting away ORMs (and therefore queryables). So Pratt's rule that for something to be considered a repository, it must return queryables is just odd. And without that rule, no distinction remains between "good" services and "bad" repositories. – MarredCheese Jul 07 '21 at 05:27
-
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
}
}

- 1,568
- 1
- 9
- 6
-
3I 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 – Dec 12 '12 at 21:08
-
2
-
87
-
19DbContext 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. – Daniel Little Dec 03 '13 at 04:34
-
1There 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. – Piotr Perak Mar 05 '14 at 23:09
-
1I just wanted to add my perspective of how [Entity Framework is not a repository](http://stackoverflow.com/questions/13180501/what-specific-issue-does-the-repository-pattern-solve/13189143#13189143) – Eric King Mar 06 '14 at 15:16
-
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 – Thunder Dec 18 '15 at 05:13
-
1I'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 Jan 21 '16 at 10:11
-
11ColacX. 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. – Rhyous Jul 11 '16 at 22:57
-
@Shyju Can you refer a good article that mentioning of "Implement the Repository Pattern in an ASP NET MVC and WEB API" ? – Kelum Sep 07 '16 at 18:33
-
2@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. – user441521 Dec 06 '17 at 20:33
-
1yea. 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 – Shyju Dec 06 '17 at 20:35
-
2@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 Dec 18 '17 at 15:11
-
1@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 Dec 21 '17 at 18:58
-
@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 Dec 25 '17 at 23:19
-
2@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 Dec 28 '17 at 17:57
-
1@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". – ColacX Dec 30 '17 at 04:29
-
1The 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. – Pavel Donchev Dec 04 '19 at 06:00
Here's one take from Ayende Rahien: Architecting in the pit of doom: The evils of the repository abstraction layer
I'm not sure yet whether I agree with his conclusion. It's a catch-22 - on the one hand, if I wrap my EF Context in type-specific repositories with query-specific data retrieval methods, I am actually able to unit test my code (sort of), which is almost impossible with Entity Framework alone. On the other hand, I lose the ability to do rich querying and semantic maintenance of relationships (but even when I have full access to those features I always feel like I'm walking on egg shells around EF or any other other ORM I might choose, since I never know what methods its IQueryable implementation might or might not support, whether it will interpret my adding to a navigation property collection as a creation or merely an association, whether it is going to lazy or eager load or not load at all by default, etc., so maybe this is for the better. Zero-impedance object-relational "mapping" is something of mythological creature - maybe that is why the latest release of Entity Framework was codenamed "Magic Unicorn").
However, retrieving your entities through query-specific data retrieval methods means that your unit tests are now essentially white-box tests and you have no choice in this matter, since you must know in advance exactly which repository method the unit under test is going to call in order to mock it. And you're still not actually testing the queries themselves, unless you also write integration tests.
These are complex problems that need a complex solution. You can't fix it by just pretending that all your entities are separate types with no relationships between them and atomize them each into their own repository. Well you can, but it sucks.
Update: I have had some success using the Effort provider for Entity Framework. Effort is an in-memory provider (open source) that allows you to use EF in tests exactly the way you would use it against a real database. I am consider switching all the tests in this project I'm working to use this provider, since it seems to make things so much easier. It is the only solution I've found so far that addresses all of the issues that I was ranting about earlier. Only thing is there is a slight delay when starting my tests as it's creating the in-memory database (it uses another package called NMemory to do this), but I don't see this as a real problem. There's a Code Project article that talks about using Effort (versus SQL CE) for testing.
-
4Any architecture article without mentioning unit test are automatically sent to the trash bin for me. One of the point of repository pattern is to gain some test-ability. – Sleeper Smith Feb 19 '13 at 06:06
-
3You can still have unit tests without wrapping the EF Context (which is already a repository). You should be unit testing your domain / services not database queries (they're integration tests). – Daniel Little Dec 03 '13 at 04:36
-
2EF's testability has improved greatly in version 6. You may now fully mock `DbContext`. Regardless, you could always mock `DbSet`, and that's the meat of Entity Framework, anyways. `DbContext` is little more than a class to house your `DbSet` properties (repositories) in one location (unit of work), especially in a unit testing context, where all the database initialization and connection stuff is not wanted or needed anyways. – Chris Pratt Mar 06 '14 at 00:29
-
Loosing related entity navigation is bad and is counter OOP, but you'll have more control on what's being queried. – Alireza May 30 '15 at 06:58
-
To the point of testing, EF Core has come a long way with out of the box In-Memory and In-Memory with Sqlite providers to enable unit testing. Bring in docker when you need integration testing to run tests on a containerised database. – Sudhanshu Mishra Jun 27 '19 at 00:20
The reason why you probably would do that is because it's a little redundant. Entity Framework gives you a wealth of coding and functional advantages, that's why you use it, if you then take that and wrap it in a repository pattern you are throwing those advantages away, you might as well be using any other data access layer.

- 297
- 2
- 3
-
could you please tell some of the advantages for "Entity Framework gives you a wealth of coding and functional advantages"? – ManirajSS Oct 29 '15 at 15:44
-
3this is what he meant. var id = Entity.Where(i => i.Id == 1337).Single() encapsulated and wrap this in a repository you basically cannot do query logic like this from the outside, which either forces you to A add more code to the repository and the interface for fetching id. B return the entity context from the repository so that you can write the query logic (which is just nonsense) – ColacX Jan 21 '16 at 10:24
In theory I think it makes sense to encapsulate the database connection logic to make it more easily reusable, but as the link below argues, our modern frameworks essentially take care of this now.

- 251
- 1
- 3
-
I liked the article , but IMHO for enterprise apps , the abstraction layer between DAL and Bl MUST Have feature , since you couldn't know what exactly will be used tomorrow. But thanks for sharing the link – Dec 12 '12 at 21:15
-
1While personally I think it's true for e.g. NHibernate (`ISessionFactory` and `ISession` are easily mockable), it's not that easy with `DbContext`, unfortunately... – Patryk Ćwiek Dec 28 '12 at 23:02
A very good reason to use the repository pattern is to allow the separation of your business logic and/or your UI from System.Data.Entity. There are numerous advantages to this, including real benefits in unit testing by allowing he use of Fakes or Mocks.

- 211
- 2
- 8
-
I agree with this answer. My repositories are basically just extension methods, which do nothing but build expression trees. Over a VERY simple abstraction that simply provides generic functionality directly over the top of dbcontext. The only real purpose of the abstraction is to make IoC a little easier. I think people try to do things in their repositories that they shouldn't do. They make on repo per entity, or put business logic in there that should be in the services layer. You only ever actually need one simple generic repo. Its not necessary, just provides a consistent interface. – Brandon Mar 24 '16 at 04:39
-
One more thing I just wanted to add. Yes CQRS is a vastly superior methodology in MOST cases. For some clients I have worked at when the database guys dont work well with developers (which happens more often than one would think especially at banks), EF over SQL is the best option. In that specific scenario, when you have absolutely no control over your database, repository pattern makes sense. Because closely resembles the data structure and is easy to translate whats going on to the database and vise versa. Its really a political and logistical decision in my opinion. To appease the DB gods. – Brandon Mar 24 '16 at 04:56
-
3I'm actually beginning to question my earlier opinions on this. EF is a combined Unit-of-Work and Repository pattern. As Chris Pratt mentioned above with EF6 you can easily mock the Context and DbSet objects. I still believe that the data access should be wrapped in classes to shield the business logic classes from the actual data access mechanism, but to go the whole hog and wrap EF with another repository and Unit of Work abstraction seems to be overkill. – James Culshaw Mar 26 '16 at 19:33
-
I don't think this is a good answer because your supporting statement is just that there are numerous advantages while only listing one.The one you do list isn't a good reason because you can use an in-memory database for entity to do unit testing. – Joel McBeth Mar 14 '17 at 23:18
-
@jcmcbeth if you look at my comment directly above your you will see that I have changed my original opinion with regards repository pattern and EF. – James Culshaw Mar 15 '17 at 16:12
-
@JamesCulshaw I saw it, but I was responding to your answer, and your comment also doesn't address my main point, that you didn't enumerate any of the other advantages. – Joel McBeth Mar 15 '17 at 17:51
After trying out repository pattern on small project I strongly advise not to use it; not because it complicates your system, and not because mocking data is nightmare, but because your testing becomes useless!!
Mocking data allows you add details without headers, add records that violate database constraints, and remove entities that the database would refuse to remove. In the real world a single update may affect multiple tables, logs, history, summaries, etc., as well as columns such as the last-modified-date field, auto generated keys, computed fields.
In short running your test on real database gives you real results and you can test not only your services and interfaces but also database behavior. You can check if your stored procedures do the right thing with data, return the expected result, or that the record you sent to delete really deleted! Such tests can also expose issues such as forgetting to raise errors from stored procedure, and thousands of such scenarios.
I think entity framework implements repository pattern better than any of the articles I have read so far and it goes far beyond what they are trying to accomplish.
Repository was best practice on those days where we were using XBase, AdoX and Ado.Net, but with entity!! (Repository over repository)
Lastly I think too many people invest lots of time on learning and implementing repository pattern and they refuse to let it go. Mostly to prove to themselves that they did not waste their time.

- 13,345
- 2
- 38
- 57

- 59
- 2
-
1Except that you do NOT want to test your database behaviour in unit tests, as it's completely not that level of testing. – Mariusz Jamro Mar 06 '16 at 13:12
-
Yes, what you're talking about here is *integration* testing, and it is indeed valuable, but unit tests are totally different. Your unit tests should never hit a real database, but you are encouraged to add integration testing that does. – Chris Pratt Jun 15 '17 at 18:52
We have had problems with duplicate but different Entity Framework DbContext instances when a IoC container that new() up repositories per type (for example a UserRepository and a GroupRepository instance that each call their own IDbSet from DBContext), can sometimes cause multiple contexts per request (in an MVC/web context).
Most of the time it still works, but when you add a service layer on top of that and those services assume objects created with one context will correctly be attached as child collections to a new object in another context, it sometimes fails and sometimes doesn't depending on the speed of the commits.

- 144
- 2
- 8
Its due to Migrations:It is not possible to get migrations to work , as the connection string resides in the web.config. But, the DbContext resides in the Repository layer . IDbContextFactory needs to have configuration string to the database .But There is no way that migrations gets the connection string from web.config.
There are work around but I have not found a clean solution for this yet!

- 89
- 2