Introduction
This article introduces how to implement repository pattern in the ASP.NET Core, using Entity Framework Core. The repository pattern implements in a separate class library project. We will use the "Code First" development approach and create a database from model using migration. We can view this article’s sample on TechNet Gallery. We will create a single entity Student to perform the CRUD operations.
The repository pattern is intended to create an abstraction layer between the data access layer and the business logic layer of an application. It is a data access pattern that prompts a more loosely coupled approach to data access. We create the data access logic in a separate class, or set of classes, called a repository with the responsibility of persisting the application's business model.

Figure 1: Repository Pattern
As per figure 1, the repository mediates between the data source layer and the business layers of the application. It queries the data source for the data, maps the data from the data source to a business entity, and persists changes in the business entity to the data source. A repository separates the business logic from the interactions with the underlying data source. The repository pattern has some advantages which are as follows.
- As we can access data source from many locations, so we can apply centrally managed, caching, consistent access rules and logic
- As business logic and database access logic are separate, so both can be tested separately.
- It provides the code's maintainability and readability by separating business logic from the data or service access logic.
Implement Repository Pattern
First, we create two projects - one is an ASP.NET Core Web Application and another is class library project which are StudentApplication and SA.Data respectively in the solution. The class library (SA.Data) project has data access logic with repository, entities, and context so we install Entity Framework Core in this.
There is an unsupported issue of EF Core 1.0.0-preview2-final with "NETStandard.Library": "1.6.0". So, we have changed the target framework to netstandard1.6 > netcoreapp1.0. We modify the project.json file of SA.Data project to implement Entity Framework Core in this class library project. So the following code snippet for the project.json file after modification.
{
"dependencies": {
"Microsoft.EntityFrameworkCore.SqlServer": "1.0.0",
"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"
},
"frameworks": {
"netcoreapp1.0": {
"imports": [
"dotnet5.6",
"portable-net45+win8"
]
}
},
"tools": {
"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"
},
"version": "1.0.0-*"
}
We are working with Entity Framework Code First approach so the project SA.Data contains entities that are needed in the application's database. In this SA.Data project, we create two entities, one is the BaseEntity class that has common properties that will be inherited by each entity and another is Student. Let's see each entity. The following is a code snippet for the BaseEntity class.
using System;
namespace SA.Data
{
public class BaseEntity
{
public Int64 Id { get; set; }
public DateTime AddedDate { get; set; }
public DateTime ModifiedDate { get; set; }
public string IPAddress { get; set; }
}
}
Now, we create a Student entity which inherits from the BaseEntity class. The following is a code snippet for the Student entity.
namespace SA.Data
{
public class Student : BaseEntity
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string EnrollmentNo { get; set; }
}
}
Now, we define the configuration for the Student entity that will be used when the database table will be created by the entity. The following is a code snippet for the Student mapping entity (StudentMap.cs).
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace SA.Data
{
public class StudentMap
{
public StudentMap(EntityTypeBuilder<Student> entityBuilder)
{
entityBuilder.HasKey(t => t.Id);
entityBuilder.Property(t => t.FirstName).IsRequired();
entityBuilder.Property(t => t.LastName).IsRequired();
entityBuilder.Property(t => t.Email).IsRequired();
entityBuilder.Property(t => t.EnrollmentNo).IsRequired();
}
}
}
The SA.Data project also contains DataContext. The ADO.NET Entity Framework Code First data access approach needs to create a data access context class that inherits from the DbContext class, so we create a context class ApplicationContext (ApplicationContext.cs) class. In this class, we override the OnModelCreating() method. This method is called when the model for a context class (ApplicationContext) has been initialized, but before the model has been locked down and used to initialize the context such that the model can be further configured before it is locked down. The following is the code snippet for the context class.
using Microsoft.EntityFrameworkCore;
namespace SA.Data
{
public class ApplicationContext : DbContext
{
public ApplicationContext(DbContextOptions<ApplicationContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
new StudentMap(modelBuilder.Entity<Student>());
}
}
}
The DbContext must have an instance of DbContextOptions in order to execute. We will use dependency injection so we pass options via constructor dependency injection.
ASP.NET Core is designed from the ground up to support and leverage dependency injection. So, we create repository interface for student entity so that we can develop loosely coupled applications. The following code snippet for the IStudentRepository interface.
using System.Collections.Generic;
namespace SA.Data
{
public interface IStudentRepository
{
void SaveStudent(Student student);
IEnumerable<Student> GetAllStudents();
Student GetStudent(long id);
void DeleteStudent(long id);
void UpdateStudent(Student student);
}
}
Now, let's create a repository class to perform CRUD operations on the Student entity which implements IStudentRepository. This repository contains a parameterized constructor with a parameter as Context so when we create an instance of the repository we pass a context so that the entity has the same context. The following is a code snippet for the StudentRepository class under SA.Data project.
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
namespace SA.Data
{
public class StudentRepository : IStudentRepository
{
private readonly ApplicationContext context;
private readonly DbSet<Student> studentEntity;
public StudentRepository(ApplicationContext context)
{
this.context = context;
studentEntity = context.Set<Student>();
}
public void SaveStudent(Student student)
{
context.Entry(student).State = EntityState.Added;
context.SaveChanges();
}
public IEnumerable<Student> GetAllStudents()
{
return studentEntity.AsEnumerable();
}
public Student GetStudent(long id)
{
return studentEntity.SingleOrDefault(s => s.Id == id);
}
public void DeleteStudent(long id)
{
Student student = GetStudent(id);
studentEntity.Remove(student);
context.SaveChanges();
}
public void UpdateStudent(Student student)
{
context.Entry(student).State = EntityState.Modified;
context.SaveChanges();
}
}
}
We developed entity and context to create database but we will come to back on this after creating the web application project.
A Web Application Using the Repository Pattern
Now, we create a MVC application (StudentApplication). This is our third project of the application, this project contains user interface for a Student entity's CRUD operations and the controller to do these operations.
As the concept of dependency injection is central to the ASP.NET Core application, so we register both context and repository to the dependency injection during the application start up. So, we register these as a service in the ConfigureServices method in the StartUp class.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddDbContext<ApplicationContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddTransient<IStudentRepository, StudentRepository>();
}
Here, the DefaultConnection is connection string which defined in appsettings.json file as per following code snippet.
{
"ConnectionStrings": {
"DefaultConnection": "Data Source=DESKTOP-RG33QHE;Initial Catalog=RepoTestDb;User ID=sa; Password=****"
},
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
Now, we have configured settings to create database so we have time to create a database using migration. We must choose the SA.Data project in the package manager console during the performance of the following steps.
- Tools –> NuGet Package Manager –> Package Manager Console.
- Run PM> Add-Migration MyFirstMigration to scaffold a migration to create the initial set of tables for our model. If we receive an error stating the term ‘add-migration’ is not recognized as the name of a cmdlet, then close and reopen Visual Studio.
- Run PM> Update-Database to apply the new migration to the database. Because our database doesn’t exist yet, it will be created for us before the migration is applied.
Create Application User Interface
Now, we proceed to the controller. Create a StudentController under the Controllers folder of the application.
This controller has all ActionResult methods for each user interface of a CRUD operation. We first create a IStudentRepository interface instance then we inject it in the controller's constructor to get its object. The following is a code snippet for the StudentController.




Mitesh PanchaPosted Jun 25, 2021, 1:01 PM
Could not find Bootstrapmodel
Jignesh KumarPosted Aug 3, 2018, 11:53 PM
Nice article thanks for sharing its pretty good explanation
Ben HayatPosted Apr 25, 2018, 2:13 AM
Hi; Did you ever create the article on the 3-layer application (Web, DAL and BLL)? I really liked the way you kept it simple and functional.
Bhavesh JadavPosted Mar 20, 2018, 11:37 PM
Very good explanation with example.
Pappu KumarPosted Sep 27, 2017, 12:04 PM
Thanks sir. but how to implement N tier Architecture in ASP.NET Core using database first and without add reference data layer in web appluication
Bobby CoolPosted Dec 30, 2016, 6:26 AM
Very good work well explained
MaheshPosted Nov 13, 2016, 2:45 PM
Very clean and nicely explained, but i have a question.1. Where do we have our custom bussiness logic? Dont we required to have a bussiness layer between repository and controller?
Manav PandyaPosted Nov 11, 2016, 11:58 AM
Really good to have article sir