Skip to content

Repository Pattern – Generic Async Repositories in C#

Repository Pattern was first introduced in the Domain Driven Development back in 2004 and has since then gained a lot of popularity.
Today I’ll show you how you can implement a generic async version of it in C# (ASP.NET Core specifically).

The code of this blog post is available here.

DDD – Domain Driven Development

Since this blog post isn’t specifically about DDD, I will only quote what Steve Smith said in his amazing book Architecting Modern Web Apps with ASP.NET Core 2 and Azure about it:

Domain-Driven Design (DDD) is an agile approach to building software that emphasizes focusing on the business domain. It places a heavy emphasis on communication and interaction with business domain expert(s) who can relate to the developers how the real-world system works.

Repository Pattern

The Repository Pattern provides an abstraction (interface) over the data so that your application can work regardless of how the data is persisted, whether it will be saved to a database, a file or even a REDIS cache.

Repositories act almost like lists that you can add to, update, remove elements from and you would usually have one repository per entity (or value object).
This is highly useful because:

  1. The application core doesn’t know how the entities are saved, so you end up working with an interface that makes switching things up much easier in the infrastructure.
  2. It makes the application core testable. All you have to do now is mock the repository interface and test your business logic as much as possible.

But what about Entity Framework Core?

Some people consider EF to implement a repository pattern and/or UoW, which it does.
But what if you one day to decided to switch to Dapper, a REDIS cache or even a NoSQL database? EF won’t help you in that case and your architecture should be flexible enough to allow these kind of changes without breaking anything.

Implementing a Generic Async Repository

Base Entity

In order to implement a generic repository, we will need a base entity class for all the entities/aggregation roots/value objects:

Interface

The repository interface should include all the basic/useful functions that are needed from a repository without getting too specific.
Just because one entity needs a specific function doesn’t mean it belongs to the interface (will talk about this later).

EF Implementation

Now when we head to the implementation, regardless of which provider/framework you choose, it should be in the infrastructure and not in the application core.
A basic implementation of the IAsyncRepository in EF would be:

Usage in ASP.NET Core

All you have to do to use this generic repository in ASP.NET Core is to add it in Startup.ConfigureServices as a scoped service:

With this, you will be able to inject a repository of a specific entity at any time.

What about specific functions?

In case you really need a specific function in your repository, for example GetByFirstName, you can’t really add it to the interface and implement because:

  1. It’s bad design since it’s specific to a certain entity.
  2. You won’t even be able to implement it since the generic repository works on the BaseEntity which doesn’t have a FirstName property (unless you add it, which is more catastrophic…).

What you should do instead is inherit the IAsyncRepository and EfRepository:

And of course to use it you just add it as a scoped service too.
This is much elegant than just keep adding functions to the abstraction.

At first it seems like the Repository Pattern is just a waste of time, even I thought that at first. But after I started working on a large project I understood the importance of not only this pattern but DDD in general.

Published inProgramming

5
Leave a Reply

avatar
2 Comment threads
3 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
3 Comment authors
zHaytamGeeknFarshad Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
Farshad
Guest
Farshad

Thank you very much, it was a very good article for me.

Geekn
Guest
Geekn

This was super helpful. In cases where there is a related entity such as posts to a blog, would you modify the Interface to support returning related entities or strictly stick to one repository per entity?