In today’s newsletter we are going to discuss
What is Repository Design Pattern
Pros and cons
How to implement it in .NET Core
What is the concept of Unit of Work
What is Repository Design Pattern
Repository is just a class that is associated with some entity and it manages all possible actions of that entity including CRUD operation.
For example we have a Student entity then , a Student repository will contain these basic methods e.g. Add , Update , Get , GetById and Delete
The Repository Pattern is a layer that mediates between the domain and the data access layers. It's like a buffer that controls how data is accessed and manipulated
Then we inject our repositories in services/handlers and use them [ But not all the time ]
How to implement it in .NET Core
Let’s suppose we are dealing with Student entity. So its repository would look like this.
With implementation:
So the main thing to note here is that only repositories are responsible to talk with database.
Don’t forget to register dependency of your repository in your
Program.cs
We are creating a layer of abstraction here , handler has no idea how those method are working and what database is being used behind the seen.
It is common practice to use generic repositories where we have to deal with multiple CRUD operations for multiple entities
Suppose we are making a Land System where we have to deal with States, Cities ,Districts and next in the hierarchy , then generic repository would be perfect solution for that problem.
Dependency injection of open generics is little bit different , check this from a previous post :
Unit of Work
I have above mentioned that we can inject our repositories in constructor of our handler or service and use it . This is fine just for couple of repos what if those increases then this is not good approach to keep injecting every new repo in constructor.
That is where Unit of Work pattern comes into an action. We put all of our repositories in UnitOfWok
and it is responsible for pushing changes in database as well. That is how it looks like :
UnitOfWork
would be like this :
Now instead of injecting repositories we would inject our IUnitOfWork
, this approach has following benefits
More clean
It saves use from multiple injections in our desired class/services/handlers
It saves us from data leakage if multiple repositories objects have different instance of DbContext
Now we can use IUnitOfWork
in our service/handler/controller like this
Pros and Cons
These are few benefits of using this pattern
1. 𝗦𝗲𝗽𝗮𝗿𝗮𝘁𝗶𝗼𝗻 𝗼𝗳 𝗰𝗼𝗻𝗰𝗲𝗿𝗻𝘀: The repository pattern separates the logic that retrieves the data and maps it to the entity model.
2. 𝗥𝗲𝗱𝘂𝗰𝗲𝘀 𝗰𝗼𝗱𝗲 𝗱𝘂𝗽𝗹𝗶𝗰𝗮𝘁𝗶𝗼𝗻: Your data access logic can be reused across multiple projects.
3. 𝗨𝗻𝗶𝘁 𝗧𝗲𝘀𝘁𝗶𝗻𝗴: It becomes a breeze as the data access logic is decoupled from the business services.
4. 𝗛𝗶𝗱𝗲𝘀 𝗦𝗤𝗟: Hides complex SQL or query language details, offering a cleaner API for accessing data.
But no hero is without its flaws:
1. 𝗢𝘃𝗲𝗿𝗵𝗲𝗮𝗱: Implementing the repository pattern introduces a new layer, which can be an overhead for small projects.
2. 𝗚𝗲𝗻𝗲𝗿𝗶𝗰 𝗥𝗲𝗽𝗼𝘀𝗶𝘁𝗼𝗿𝗶𝗲𝘀: They can limit your ability to perform complex database operations and can lead to performance penalties.
3. 𝗟𝗲𝗮𝗿𝗻𝗶𝗻𝗴 𝗖𝘂𝗿𝘃𝗲: It takes time to understand and implement the repository pattern correctly
Covering each aspect of this topic in less than 5 minutes was difficult , I have tried to give basic overview that how it looks like using a repository pattern. For more detailed read visit Microsoft Docs
Whenever you’re ready , there are 3 ways I can help you
Promote yourself to 4600+ subscribers by sponsoring my Newsletter (Reach me at mwaseemzakir@gmail.com)
Become a Patron and get access to 130+ .NET Questions and Answers , I add 2-5 new questions every week
Get my FREE eBook from Gumroad that contains 30 .NET Tips (Downloaded by 2500+ and 100+ five star ratings)
Special Offers 📢
Ultimate ASP.NET Core Web API Second Edition - Premium Package
10% off with discount code: 9s6nuez
Great article! About Generic Repository, we can still use for complex queries using the Specification Pattern, right?
The concern about performance remains.
Very helpful thanks for sharing :)