This is, hopefully, a critical review of whether the repository and UnitOfWork pattern is still useful with the modern implementations of Microsoft’s Entity Framework ORM. I look at the reasons why people are suggesting the repository pattern is not useful and compare this with my own experience of using the repository and UnitOfWork over many years.
This is a series:
- Part 1: Analysing whether Repository pattern useful with Entity Framework (this article).
- Part 2: Four months on – my solution to replacing the Repository pattern.
- UPDATE (2018): Big re-write to take into account Entity Framework Core, and further learning.
I have just finished the first release of Spatial Modeller™ , a medium sized ASP.NET MVC web application. I am now undertaking a critical review of its design and implementation to see what I could improve in V2. The design of Spatial Modeller™ is a fairly standard four layer architecture.
I have use the repository pattern and UnitOfWork pattern over many years, even back in the ADO.NET days. In Spatial Modeller™ I think I have perfected the design and use of these patterns and I am quite pleased with how it helps the overall design.
However we don’t learn unless we hear from others that have a counter view, so let me try and summarise the arguments I have seen against the repository/Unit of Work pattern.
What people are saying against the repository pattern
In researching as part of my review of the current Spatial Modeller™ design I found some blog posts that make a compelling case for ditching the repository. The most cogent and well thought-out post of this kind is ‘Repositories On Top UnitOfWork Are Not a Good Idea’. Rob Conery’s main point is that the repository & UnitOfWork just duplicates what Entity Framework (EF) DbContext give you anyway, so why hide a perfectly good framework behind a façade that adds no value. What Rob calls ‘this over-abstraction silliness’.
Another blog is ‘Why Entity Framework renders the Repository pattern obsolete’. In this Isaac Abraham adds that repository doesn’t make testing any easier, which is one thing it was supposed to do.
I should also say I found another blog, ‘Say No to the Repository Pattern in your DAL’ which, says that using a repository removes access to Linq querying, ability to include/prefetch or aync support (EF 6). However this not true if your repository passes IQueryable items as this allows all these features.
So, are they right?
Reviewing my use of repository and UnitOfWork patterns
I have been using repositories for a while now and my reflection is that when the ORMs weren’t so good then I really needed repositories.
I build a geographic modelling application for a project to improve HIV/AIDS testing in South Africa. I used LINQ SQL, but because it didn’t support spatial parts I had to write a lot of T-SQL stored procedures and use ADO.NET to code access the spatial values. The database code was therefore a pretty complicated mix of technologies and a repository pattern acted as a good Façade to make it look seamless. I definitely think the software design was helped by the repository pattern.
However EF has come a long way since then. Spatial Modeller™ used EF 5, which was the first version to support spatial types (and enums, which is nice). I used the repository pattern and they have worked well, but I don’t think it added as much value as in the South Africa project as the EF code was pretty clean. Therefore I sympathise with the sentiments of Rob etc.
My views on the pros and cons of repository and UnitOfWork patterns
Let me try and review the pros/cons of the repository/UnitOfWork patterns in as even-handed way as I can. Here are my views.
Benefits of repository and UnitOfWork patterns (with best first)
- Domain-Driven Design: I find well designed repositories can present a much more domain specific view of the database. Commands like GetAllMembersInLayer make a lot more sense than a complex linq command. I think this is a significant advantage. However Rob Conery’s post suggests another solution using Command/Query Objects and references an excellent post by Jimmy Bogard called ‘Favor query objects over repositories’.
- Aggregation: I have some quite complex geographic data consisting of six or seven closely interrelated classes. These are treated as one entity, with one repository accessing them as a group. This hides complexity and I really like this.
- Security of data: one problem with EF is if you load data normally and then change it by accident it will update the database on the next SaveChanges. My repositories have are very specific what it returns, with GetTracked and GetUntracked versions of commands. And for things like audit trails I only ever return them as untracked. (see box below right if you not clear on what EF tracking is).
- Hiding complex T- SQL commands: As I described before sometimes database accesses need a more sophisticated command that needs T-SQL. My view these should be only in one place to help maintenance. Again I should point out that Rob Conery’s post Command/Query Objects (see item 1) could also handle this.
A normal EF database command using DbContext returns ‘attached’ classes. When SaveChanges() is called it checks these attached classes and writes any changed data back to the database. You need to append AsNoTracking() to the linq command if you want a read-only copy. Untracked classes are also slightly faster to load.
Non-benefits of repository and UnitOfWork patterns are:
- More code: Repositories and UnitOfWork is more code that needs developing, maintaining and testing.
- Testing: I totally agree with Isaac Abraham. Repositories are no easier to mock than IDbSet. I have tried on many occasions to mock the database, but with complex, interrelated classes it is really hard to get right. I now use EF and a test database in my unit tests for most of the complex models. It’s a bit slower but all my mocks could not handle the relational fixup that EF does.
I have to say I think Command/Query Objects mentioned by Rob Conery and described in detail in Jimmy Bogard’s post called ‘Favor query objects over repositories’ have a lot going for them. While the repository/UnitOfWork pattern has served me well maybe EF has progressed enough to use it directly, with the help of Command/Query Objects to make access more Domain-Driven in nature.
What I do in a case like this is build a small app to try out a new approach. I ensure that the app has a few complex things that I know have proved a problem in the past, but small enough to not take too long. This fits in well with me reviewing the design of Spatial Modeller™ before starting on version 2. I already have a small app looking at using t4 code generation to produce some of the boiler plate code and I will extend the app to try a non-repository approach. Should be interesting.
Great Article Jon!
After reading the above article on UoW/repository pattern, which touched on DTO’s, I’d like to know how you’ve implemented
moving data in and out of your DTO from your EF entites.
I’m about to embark on a new project using Automapper to relate DTOs and EF entities but I have reservations about doing so
due to several online articles that warn of various issues using Automapper with EF. These warnings usually refer to updating
an EF entity that has a navigation property from data updated in the DTO.
I can understand Automapper creating a new EF entity when an existing source object hasn’t been fed into the mapping or perhaps issues
with poor configration of navigation properties/data (virtual/include/load) being the root cause of DTO => EF entity
problems. See http://visualstudiomagazine.com/blogs/tool-tracker/2013/11/updating–entities-with-automapper.aspx
Are you aware of any other issues? Have you encountered any “gotchas” going from DTO to EF entity? What do you use to map
DTO to EF entities? Should we simply use .Ignore() on the DTO => EF entity map and target only the parent entity for the update?
Keep up the great work!
Thanks for your question. As you say in the second part of this article (see https://thereformedprogrammer.net/is-the-repository-pattern-useful-with-entity-framework-part-2/) I do indeed use DTOs between the EF (Entity Framework) and the Ui/WebApi layer. I have developed open-source library called GenericServices (see https://github.com/JonPSmith/GenericServices) with two example sites: http://samplemvcwebapp.net/ and http://complex.samplemvcwebapp.net/ . The last one is working with the AdventureWorksLite2012 database which is a database with both linked classes and composite keys, as described in this article https://www.simple-talk.com/dotnet/asp.net/using-entity-framework-with-an-existing-database–user-interface/
The two articles refer to the problem of updating EF entities that have navigation property, i.e. another class connected by some form of foreign key. This problem isn’t special to using DTOs or AutoMapper, but is a common issue in EF that you can fall over even if hand coding the update.
AutoMapper only makes it harder as the ‘simple’ answer looks fine from the outside. That is because AutoMapper does some ‘magic’ to automate the mapping. As I explain in my article on what makes a good software library (see https://thereformedprogrammer.net/what-makes-a-good-software-library/) you need to be careful to understand ‘magic’ libraries otherwise it might trip you up.
As you the question in your last paragraph here are my answer:
1. ‘I have encountered any “gotchas” going from DTO to EF entity?’. The answer is yes, but I have found workrounds for 95% of the cases. Sometimes I hand-code the translation between DTO and EF entities, but that is normally for cases where the workround is more work than writing the code directly.
2. ‘What do you use to map DTO to EF entities?’ My GenericServices library does use AutoMapper, but with some extra features provided by overriding various methods inside GenericService’s DTOs and some attributes.
3. ‘Should we simply use .Ignore() on the DTO => EF entity map’. I think you are asking my opinion on whether you should only use DTOs fro reading data out of a database, but not for writing back. I do use AutoMapper for both read and write, but under the strict control of GenericServices. Interestingly Jimmy Bogard, the author of AutoMapper, does NOT recommend using AutoMapper for writes, only for reads. See some very interesting comments he made on a detractor’s blog
article. See read the first comment on http://www.uglybugger.org/software/post/friends_dont_let_friends_use_automapper which is from Jimmy.
Long answer, but an interesting architectural issue I have grappled with quite a bit. My current opinion is that AutoMapper allows me to create applications much quicker so I am happy to learn its foibles.
I just wanted to add a point here around the DTO to EF Entities mapping and in particular the persistence issues that can be encountered. I almost gave up on this due to the poorly implemented(partial implementation IMHO) change tracking for re-attached entities. Take a simple usage scenario – retrieve a DTO and pass it to the UI – here the user changes some properties, deletes a related item from a property collection and adds an item to another and hits save. DTO mapped back to EF entity and then attached to a DbContext. You’d think you could just call SaveChanges and be done. In fact things just got complicated and really painful and this is a simple use case.
EF(v6.1 in my case) makes hard work of this as it does not persist(add,update or delete) related entities re-attached to the DbContext – you have to do all the hard work, working out the changes to get the persistence to cascade. Isn’t this something that should be part of EF implementation out of the box? It really should be. Frankly, this was such a show stopper that we were prepared to walk away from the whole DDD pattern we had built around a repository pattern using EF.
GraphDiff was the silver bullet for our project and made this pattern work for us:
I posted a comment along these lines in response to an article describing the AutoMapper=>EF=>DTO combination as flawed pattern : http://rogeralsing.com/2013/12/01/why-mapping-dtos-to-entities-using-automapper-and-entityframework-is-horrible
Thanks for your comment and I agree with you! I am so used to this problem that I most likely forget how complicated it is. One of my earliest posts was about the problem of updating many-to-many relationships, which got me into the whole EF handling of relationships.
Yep, it is difficult updating relationships in EF via DTOs (AutoMapper or no AutoMapper). I do it all the time and I have worked out how to do it, but it isn’t obvious.
In GenericServices I have included a number of extension points which allows me to sort out relationships before writing to the database. It still needs thought, but it is doable. For example in the demo site SampleMvcWebApp I have some code to sort out the relationships between tags and posts (see actual code here in line 142 onwards). GenericServices also have a special `DeleteWithRelationships` method to handle that problem too. (Note: I have written two articles on both of these subjects on this blog – look in the Archive for posts starting with ‘GenericServices Masterclass’)
The GraphDiff looks like a great find – thanks for bringing that to my attention and I will have a look at it. I have kind of got to grips with EF relationships/SQL foreign keys and can handle them now, but maybe when I update GenericServices to EF 7 I might look at GraphDiff .
Thanks @bbqchickenrobot. I have now created a second post which goes into detail on my solution for replacing the Repository pattern. Bit more complicated than I thought it would be, but in that change is a stronger move over to Domain-Driven Design. Hope you like it.
Great summation of the repo + UoW patterns. Also, great for providing an update regarding the Command/Query pattern as well with some great links for research!