ASP.NET Core Entity Framework Repository Pattern in a WEB API

In this post, I will show how to implement ASP.NET Core Entity Framework Repository Pattern in a WEB API if you are not familiar with ASP.NET Core web API, No need to worry I will show you how to do that using the steps below.

Repository pattern is a way to create better code architecture. This pattern will focus on the interface instead of using the actual class of your methods. This architecture will allow us to easily change the implementation of the method inside an interface if ever you might want to change it later. The interface is consists of static methods, inputs and return type. I will demonstrate it by creating an ASP.NET Core Web API project.

Note: I created this project using Visual Studio Code. Make sure you have it installed in your machine. If not Visual Studio would also be fine.

I. Create ASP.NET Core Web API project

  1. Create a new folder for your project.
  2. Open a command prompt and navigate to your folder location using the cd command. (ex. cd folder name)
  3. Type “code .”, this will open your project directory inside visual studio code.
  4. Open Visual Studio Code Terminal and create a new ASP.NET Core web API project using this command “dotnet new webapi -n coreApi”.
Create asp.net core Webapi
This will create a web api project with coreApi name

5. You can remove sample controller WeatherForecastController to start a clean project solution. See the image below.

Default scaffolds
Remove files

We also need this packages. Install this package using the command below.

dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.SqlServer

Create ASP.NET Core in Visual Studio using CLI

II. Setup Database Connection for Entity Framework

1. Add your SQL database connection string inside your appsettings.json.

"ConnectionStrings": {
    "default": "Data Source=DESKTOP-4DU98BI\SQLEXPRESS01;User ID=username;Password=password;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"
  },

2. Configure your application to Use SQL Server in your Startup.cs. Put the code below inside ConfigureServices method.

string connectionString = Configuration.GetConnectionString("default");
services.AddDbContext<AppDBContext>(c => c.UseSqlServer(connectionString));
Startup configuration

III. ASP.NET Core Entity Framework Repository Pattern Structure

  1. Create a folder Interfaces, then create repository Interface class this will contains a method for essential CRUD functions.
Interface folder
Interfaces folder

Below are the methods declare on our IRepository interface:

MethodDescription
SelectAllSelect all record
SelectByIdSelect record by id
CreateAsyncInsert record
UpdateAsyncUpdate record by id
DeleteAsyncDelete record by id
IRepository Interface

IRepository.cs


using System.Collections.Generic;
using System.Threading.Tasks;

namespace coreApi.Interfaces
{
    public interface IRepository
    {
        Task<List<T>> SelectAll<T>() where T : class;
        Task<T> SelectById<T>(long id) where T : class;
        Task CreateAsync<T>(T entity) where T : class;
        Task UpdateAsync<T>(T entity) where T : class;
        Task DeleteAsync<T>(T entity) where T : class;
    }
}

2. Configure Interface Implementation class by creating a Models folder then create a class named Repository. This class will serve as the implementation method for the IRepository interface. We will configure this class to accept the DBContext parameter; this way, we can easily change DBContext if we change our database. All method from this class will take a model entity to map to a table from the database.

Repository Class
Repository class under Models
using System.Collections.Generic;
using System.Threading.Tasks;
using coreApi.Interfaces;
using Microsoft.EntityFrameworkCore;

namespace coreApi.Models
{
    public class Repository<TDbContext> : IRepository where TDbContext : DbContext
    {
        protected TDbContext dbContext;

        public Repository(TDbContext context)
        {
            dbContext = context;
        }

        public async Task CreateAsync<T>(T entity) where T : class
        {
            this.dbContext.Set<T>().Add(entity);

            _ = await this.dbContext.SaveChangesAsync();
        }

        public async Task DeleteAsync<T>(T entity) where T : class
        {
            this.dbContext.Set<T>().Remove(entity);

            _ = await this.dbContext.SaveChangesAsync();
        }

       public async Task<List<T>> SelectAll<T>() where T : class
        {
            return await this.dbContext.Set<T>().ToListAsync();
        }


        public async Task<T> SelectById<T>(long id) where T : class
        {
            return await this.dbContext.Set<T>().FindAsync(id);
        }

        public async Task UpdateAsync<T>(T entity) where T : class
        {
            this.dbContext.Set<T>().Update(entity);

            _ = await this.dbContext.SaveChangesAsync();
        }
    }
}   

3. Create a member model, later on we will create a migration and update database using this model to create a table.

member model
member model

member.cs

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace coreApi.Models
{
    public class member
    {
        [Key]
        public long Id { get; set; }
        [Column(TypeName = "nvarchar(50)")]
        public string FirstName { get; set; }

        [Column(TypeName = "nvarchar(50)")]
        public string LastName { get; set; }
        
        [Column(TypeName = "nvarchar(50)")]
        public string MiddleName { get; set; }
    }
}

4. Create a DBContext class inside Models folder name it AppDBContext, this class handles the Database connection.

AppDBContext.cs

using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using coreApi.Models;
namespace coreApi.Models
{
    public class AppDBContext: DbContext
    {
        private readonly DbContextOptions _options;
        public AppDBContext(DbContextOptions options) : base(options)
        {
            _options = options;
        }

        public DbSet<member> members { get; set; }

       protected override void OnModelCreating(ModelBuilder modelBuilder)
       {
         base.OnModelCreating(modelBuilder);
       }

    }
}

5. To be able to link IRepository and Repository class, we need to add scope inside ConfigureServices from your Startup.cs. We also need to pass the DBContext parameter to the Repository class. Copy the code below to your Startup.cs.

services.AddScoped<IRepository, Repository<AppDBContext>>();

6. Create a migration. Open Visual Studio Code terminal and execute the command below.

dotnet ef migrations add create_table_member

This command will create a Migrations folder and class that contains SQL scripts for Database tables, which in this case is the member table.

MIgration File
Migration Files

7. Execute Database Update. This method create the Database and tables from the migration file that we created in step 6.

dotnet ef database update

8. Create a Sample Controller. In my case, I name it SampleController. Open the file and paste the code below. This code calls the DBContext and scoped that we set up from our Startup.cs. Instead of using the actual implementation, we are going to use the interface class, which is the IRepository.

ASP NET Core Entity Framework Repository Pattern in a WEB API-Controllers
SampleController
 private readonly IRepository _repository;
 public SampleController(AppDBContext context, IRepository repository)
 {
    _repository = repository;
 }

9. This step, we will create a CRUD function using the implementation of our Repository Class. If you still remember from step 2, we configure our Repository class to accept model entity, so in every method, we pass the member model which represent the table entity were we want to select, Insert, update and delete a data.

SampleController.cs

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using coreApi.Interfaces;
using coreApi.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
namespace coreApi.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class SampleController : ControllerBase
    {
        private readonly IRepository _repository;
        public SampleController(AppDBContext context, IRepository repository)
        {
            _repository = repository;
        }

        [HttpGet]
        public async Task<ActionResult<IEnumerable<member>>> GetMember(int page = 0, int pageSize = 5)
        {
            var model =  await _repository.SelectAll<member>();
            return model;
        }

        [HttpGet("{id}")]
        public async Task<ActionResult<member>> GetMember(long id)
        {
            var model = await _repository.SelectById<member>(id);

            if (model == null)
            {
                return NotFound();
            }

            return model;
        }

        [HttpPut("{id}")]
        public async Task<IActionResult> UpdateMember(long id, member  model)
        {
            if (id != model.Id)
            {
                return BadRequest();
            }

            await _repository.UpdateAsync<member>(model);

            return NoContent();
        }

        [HttpPost]
        public async Task<ActionResult<member>> InsertMember(member model)
        {
            await _repository.CreateAsync<member>(model);
            return CreatedAtAction("GetMember", new { id = model.Id }, model); 
        }

        [HttpDelete("{id}")]
        public async Task<ActionResult<member>> DeleteMember(long id)
        {
            var model = await _repository.SelectById<member>(id);

            if (model == null)
            {
                return NotFound();
            }

            await _repository.DeleteAsync<member>(model);

            return model;
        }
    }
}

Now, You have successfully Implemented an ASP NET Core Entity Framework Repository Pattern in a WEB API. To test your application, run your project using the command below.

CommandDescription
dotnet buildBuild Project Solution
dotnet runRun Solution
dotnet watch runRun solution and watch for any changes in your project
Run Command

You can access the method using the url below. Root address might be different from your end you can verify it once you run your project.

ASP NET Core Entity Framework Repository Pattern in a WEB API
Localhost Address
UrlController MethodHttp Method
http://localhost:5000/api/Sample/GetMemberHttpGet
http://localhost:5000/api/Sample/InsertMemberHttpPost
http://localhost:5000/api/Sample/UpdateMemberHttpPut(“{id}”)
http://localhost:5000/api/Sample/{id}GetMember(long id)HttpGet(“{id}”)
Url Address

For the post method, you need to put the parameter inside the request body and use application/JSON for the headers Content-Type. Below is a sample postman request.

ASP.NET Core Entity Framework Repository Pattern in a WEB API
Postman Sample request

Request Headers

ASP NET Core Entity Framework Repository Pattern in a WEB API

Source Code: GitHub link

Conclusion

Repository pattern makes your code structure more flexible and reusable. This technique allows you to use an interface instead of using the actual class for your methods. That means by using the interface, you are pre structuring all the inputs and return value of specific methods. And create a class and extend it using this interface to have the actual implementation. This structure will help you to change the implementation of every method with less modification easily.

Hope this helps and share if you think this was helpful. Please also do visit my Blog Page for my other ASP.NET Core tutorials.

Leave a Comment

%d bloggers like this: