In the first example, we use context.Orders, in the second we use repository.GetOrders(). Here’s the result:Ĭan you see the difference between these two code snippets? The only difference is in the first line. When your repository methods return IQueryable, someone else is going to get that IQueryable and compose a query on top of it. Here we are directly using a DbContext without the repository pattern. The result is slimmer, cleaner, more maintainable and easier-to-test actions. With the repository pattern, we encapsulate these queries inside repository classes. Also, as your application grows, the chances of you repeating a fat query in multiple places increases. These queries make it hard to read, understand and test actions in ASP.NET MVC controllers. One of the reasons we use the repository pattern is to encapsulate fat queries. If you want to learn how to implement the repository and unit of work pattern together, watch my YouTube video here. No need for two separate calls to the Save() method! No need to wrap this block inside a transaction. The database will always be in a consistent state. Now, either both objects are saved together or none are saved. With the unit of work, we can re-write that ugly code like this: Yes, we can wrap that whole thing inside a transaction to make it even more ugly!Ī pattern that goes hand in hand with the repository pattern is the unit of work. What if one of these calls to the Save() method fails? You’ll end up with a database in an inconsistent state. Here’s an example:Ĭan you see the problem in this code? For each change, we need a separate call to the Save() method on the corresponding repository. And then you want to persist the changes across multiple repositories in one transaction. Do collections have a Save() or Update() method? No! Here’s an example:Īnother reason your repositories should not have a Save() method is because sometimes as part of a transaction you may work with multiple repositories. I repeat: think of a repository as a collection of domain objects in memory. Yet another very common mistake! As I’ve explained in my YouTube video before, your repositories should not have a Save() or Update() method. What if you return OrderViewModel but somewhere else you need OrderDetailsViewModel or OrderSnapshotViewModel? So, the client of the repository should decide what it wants to map the Order object to. By mapping the domain objects to view models (or something else) inside a repository, you prevent the client of your repositories from getting access to the underlying domain object. Your repositories should return domain objects and the client of the repository can decide if it needs to do the mapping. It’s the responsibility of your controllers. Mapping is not the responsibility of the repository. I’ve seen many students using AutoMapper inside their repository methods: So it should not return view models/DTOs or anything that is not a domain object. Once again, a repository is like a collection of domain objects. Repositories that return view models/DTOs Instead, you should have a separate repository per domain class, like OrderRepository, ShippingRepository and ProductRepository. If you’re building an application called Vega, you shouldn’t have a repository like the following: You should think of a repository as a collection of domain objects in memory. While reviewing various solutions, I’ve encountered a few common mistakes in the implementation of the repository pattern. It’s the number one language employers are looking for and gives you 4x more job opportunities than C#.Īs part of my new ASP.NET Core course, I’ve been encouraging my students to post their code to GitHub. UPDATE (Nov 5 2018): While you’re here to become a better C# developer, I strongly recommend you to watch my Python tutorial on YouTube. April 3rd, 2017 Comments 4 Common Mistakes with the Repository Pattern
0 Comments
Leave a Reply. |