2

Entity Framework Core Generic Repository

Introduction

Entity Framework Core Generic Repository – Behold! The topic that some people will frown upon. They don’t even wanna talk about it. However, others love it, they feel all excited on the mention of generic repository pattern.

As with everything, the generic repository pattern has its pros and cons. You are the one to decide if it’s a good fit for your project. You can always use it only for parts of your application, you don’t have to go all in with generic repository pattern!

The advantage of having generic CRUD repository is that you can inherit from it, pass it entity type and you have CRUD repository for any entity type with a minimal amount of code.

Note: We will not build something bullet-proof that will cover all of your needs in future. Rather, we will try to build a base for a generic repository that you will be able to use to create CRUD operations easily and later extend per your needs.  So, this will only cover Generic Repository that does CRUD. For anything additional, you could inherit from GenericRepository class and extend it. This is just a proof of concept. In larger real-world applications you don’t want your Web layer to be aware of your Database layer. Hence, you will not be injecting repositories in your controllers.

Again, you could only use it for parts of your application. You don’t have to use it as a de-facto solution for all of your database needs.

Sample code – here.

 

Set up the DbContext

I will create a new MVC template with ASP.NET Core 2, without auth.

Let’s set up DbContext and some sample DB Entity class. Here is the Category Database Entity:

And here is the DbContext:

You can see we have Categories DbSet which represents a matching table in the database.

We are creating a constructor that accepts DbContextOptions as a parameter. This will enable us to pass in options from ConfigureServices in Startup class:

We will add a connection string to appsettings.json so I can actually interact with the database:

Before being able to use Entity Framework’s command line tool I need to add it to my project. I will manually edit the .csproj file and this:

For changes to take effect I have to restore packages (you don’t have to do this if you are using Visual Studio to make these changes):

Now I am ready to add initial migration and apply it to the database:

 

Building generic repository

Just like with Entity Framework 6, in EF Core we use DbContext to query a database and group together changes that will be written back to the store as a unit.

The great thing about DbContext class is that it’s generic and therefore supports generics on methods that we will use to interact with the database.

IGenericRepository interface

The base interface that we will use looks like this:

The first thing you will notice is generic TEntity type, that will be the type of our entity in Database (Category, User, Role, etc.).

We also set a constraint that TEntity needs to be class. We can also use some interface to mark an entity and use that interface in each of entity classes. But we will talk about that later.

GetAll returns IQueryable because we don’t want to return full list. However, we want to return something that caller will be able to use to further process the query. Maybe filter it by something, do paging, etc. That’s no interest of us for now.

Other method signatures are probably just like you would expect them. However, you might notice Task in front of the methods. That is because these methods will be async because we will be making use of Entity Framework’s async support.

Let’s start implementing generic repository:

We will have ASP.NET Core inject DbContext for us that’s why we are passing it in as a constructor parameter.

Now you will see that compiler is complaining because we are not implementing IGenericRepository. Time to do that!

The GetAll method is pretty straightforward:

We simply return the belonging DbSet for the Entity. And since DbSet implements IQueryable we can use it to process the queryable further later on. We are using AsNoTracking extension to make things faster and prevent any updates to this specific IQueryable collection. In your project you probably don’t want this in your web layer, yo woud use a layer between to process your entities.

And then we have GetById method.

It simply gets the data for given id and finds the entity with this unique id.

And then there are methods that actually do change in database:

For each method, we use the appropriate method to do the operation and afterwards we save the changes, making use of EF’s SaveChangesAsync() method.

In Delete method, we use our existing GetById method to fetch the existing entity from DB and then we pass in that entity to Remove method od DbSet.

 

Injecting repository in controller

Let’s create an interface for Category repository:

This inherits from IGenericRepository interface, meaning that we will have to implement all these methods.

However, if we create a CategoryRepository that inherits from GenericRepository, we will cover all those methods from IGenericRepository. Also, we have to implement also ICategoryRepository.

This is how it would look like:

By inheriting from GenericRepository we just have CRUD done for CategoryRepository. Which is great! You write a small amount of code and you get CRUD done for any entity type.

However, we also need to implement ICategory repository, so our CategoryRepository class will look like this:

 

Fetching the actual data

For us to be able to use CategoryRepository inside of our code we have to add it to DI container:

Now we can inject it in the controller:

 

Share now!
Ibrahim Šuta
 

  • Good point! Thanks. I updated the code. I added the AsNoTracking part, so it’s not tracked by the DbContext.

    That’s the case when we are tracking the DB Entity. I forgot to add the code for that.

  • Ather Ali

    Nice article Thanks !!!.. I am getting an error in generic repository where it says DbSet.does not contain a definition for “AsNoTracking() “, I am using EF Core 2.0.. Please seuggest an alternate solution ?