Entity Framework Core in ASP.NET Core 3.1

This article will be covering in detail the implementation of Entity Framework Core in ASP.NET Core Web API. We will learn about entity framework core in details i.e. what, how & why and see how to use it in ASP.NET Core Web API to implement CRUD operations. Though here we will be using entity framework in ASP.NET Core this can be implemented even in .NET Framework for your data persistence. I hope you will join me on this and go through step by step demonstration on implementing entity framework core in ASP.NET Core Web API.

Introduction to Entity Framework Core

ASP.NET Core Entity Framework

Entity Framework has been around since 2008 which has improved over the years. Entity framework core was introduced for .NET Core based applications. It is an open-source object-relational mapper (ORM) built over ADO.NET and an official data access platform from Microsoft. Entity framework core has been rewritten from scratch to make it lightweight, flexible & achieve better performance.

In the absence of an ORM typically lots of code have to be written to perform CRUD operations with the database. using an ORM like entity framework can reduce the number of lines of code to be written for database interactions. Typical ORM will work on classes & database tables of similar structure but entity framework core implements mappings which makes it a lot more flexible i.e. in case table & class does not match then mappings can be exercised to get from objects to tables.

Entity framework core can work with wide variety of databases. Microsoft provides rich providers for SQL Server & SQLite and there are many other third party providers some commercial and some from community.

How does entity framework core works?

How Entity Framework Works
  1. Define domain classes & configure entity framework DbContext API along with mappings to let entity framework work how this class maps to the database schema.
  2. Write LINQ to objects to fetch data from the database.
  3. Based on mappings & database provider configured entity framework will translate queries into SQL that’s understood by the database.
  4. The query is executed and the object is populated with data.
  5. Data in objects can be modified, deleted or new records can be added to the list & once done call DbContext.saveChanges from EF API to save data back to the database.
  6. The entity framework will generate the required SQL statements to save data back to the database.

Should we use Entity Framework Core?

Entity framework can increase developer productivity but still many developers don’t prefer using it due to the complexity it adds to data access layer.

Use entity framework when

  • There is a one-to-one mapping between fields on-screen and columns in the database tables.
  • You need to implement CRUD operation for the screen and business logic is not so complex.
  • There are no bulk database operations to be implemented.
  • There is no need to bother about the SQL generated for the operation i.e. no SQL tweaking are required for the performance

Code First v/s Database First Approach

Entity Framework Database First vs Code First Approach

Entity framework provides two approaches for development

  1. Database First Approach: This is used when you already have a database ready or you have a team of DBAs and take the approach that you will be designing the database first and then the application. Entity framework will create Entities for you from the database. Manual changes to the database can be done and the model can be updated from the database.
  2. Code First Approach: This is used when there is a team of developers who need full control over the code. The entity framework will generate database tables for you based on the domain classes. Here database is just storage with no business logic in the database layer. Any manual changes to the database will be lost.

Implement Entity Framework Core in ASP.NET Core Web API

Demonstration video

Create a project for demonstration

For demonstration purposes, we will be creating a default ASP.NET Core 3.1 API Project using Visual Studio 2019 Community Edition. We will be using the code-first approach for the demonstration.

ASP.NET Core 3.1 API Project Creation

Create the data model

Create an Employee entity class. Here Id will become the primary key column for the database table that will be created for this class. Entity framework interprets property named as Id or ID as the primary key

public class Employee
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }
    public string Designation { get; set; }
    public double Salary { get; set; }
}

Install Entity Framework Core Packages

We need to install the required entity framework packages. You run the below mentioned commands in Package Manager or install required Nuget packages from Nuget Package Manager.

Install-Package Microsoft.EntityFrameworkCore
Install-Package Microsoft.EntityFrameworkCore.Design
Install-Package Microsoft.EntityFrameworkCore.SqlServer
Install-Package Microsoft.EntityFrameworkCore.Tools
Install Entity Framework Core

Adding database context class

This is the main class that co-ordinates entity framework functionality for a given model class. You need to derive the class from entity framework DbContext class and specify the entities included in the data model. This class creates a DbSet property for the Employee entity set. An entity set typically represents a database table and an entity represents a row in the table.

Database table will have the same name as DbSet property name.

public interface IApplicationDbContext
{
    DbSet<Employee> Employees { get; set; }
    Task<int> SaveChanges();
}
public class ApplicationDbContext : DbContext, IApplicationDbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    public DbSet<Employee> Employees { get; set; }

    public new async Task<int> SaveChanges()
    {
        return await base.SaveChangesAsync();
    }
}

Connect application to the database

Specify the SQL Server connection string in appsettings.json file. We are using localdb database which is light-weight version of the SQL Server Express database engine.

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\mssqllocaldb;Database=EFCoreDb;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

Newsletter Subscription

Stay updated! Instantly get notified about my new articles in your mailbox by subscribing via email

Register database context for dependency injection in Startup class

You need to configure the database context as service in configureservices in the startup.cs file so that you pass this service to the controller through the constructor parameter.

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
        Configuration.GetConnectionString("DefaultConnection"),
        ef => ef.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName)));
    services.AddScoped<IApplicationDbContext>(provider => provider.GetService<ApplicationDbContext>());

    services.AddControllers();
}
//Remaining code has been removed

For more details on Dependency Injection, you can read my another article – https://procodeguide.com/programming/dependency-injection-in-asp-net-core-3/

Add Migrations

To automate the migrations from our entity framework class the database we need to run the command add-migration in the package manager console.

add-migration FirstMigration

This will add migration folder & required migration files to the solution as shown below. These files will be on the basis entities we configured.

Entity Framework Migrations

To create database from the migration created above we need to command update-database in the package manager console

update-database

The database as shown below will be created based on entities configured. Here it has created an Employee table based on the Employee model configured.

Entity Framework Core - Code First Database

Add CRUD operations in Repository for Employee

Repository is a component that encapsulated the objects related to data store and operations performed over them. You can even write a generic repository but for demonstration purpose I have added a repository specific to Employee entity. Interface will contain the operations that are possible (based on requirements) on the entity i.e. CRUD operations. DbContext is passed as parameter in constructor using dependency injection. Here we have added following operations.

  • Create – to add a new employee
  • GetAll – to get a list of all employees
  • GetById – to get particular employee by Id
  • Update – to modify existing employee
  • Delete – to delete existing employee
public interface IEmployeeRepository
{
    Task<int> Create(Employee employee);
    Task<List<Employee>> GetAll();
    Task<Employee> GetById(int id);
    Task<string> Update(int id, Employee employee);
    Task<string> Delete(int id);
}
public class EmployeeRepository : IEmployeeRepository
{
    private IApplicationDbContext _dbcontext;
    public EmployeeRepository(IApplicationDbContext dbcontext)
    {
        _dbcontext = dbcontext;
    }

    public async Task<int> Create(Employee employee)
    {
        _dbcontext.Employees.Add(employee);
        await _dbcontext.SaveChanges();
        return employee.Id;
    }

    public async Task<List<Employee>> GetAll()
    {
        var employees = await _dbcontext.Employees.ToListAsync<Employee>();
        return employees;
    }

    public async Task<Employee> GetById(int id)
    {
        var employee = await _dbcontext.Employees.Where(empid => empid.Id == id).FirstOrDefaultAsync();
        return employee;
    }

    public async Task<string> Update(int id, Employee employee)
    {
        var employeeupt = await _dbcontext.Employees.Where(empid => empid.Id == id).FirstOrDefaultAsync();
        if (employeeupt == null) return "Employee does not exists";

        employeeupt.Designation = employee.Designation;
        employeeupt.Salary = employee.Salary;

        await _dbcontext.SaveChanges();
        return "Employee details successfully modified";
    }

    public async Task<string> Delete(int id)
    {
        var employeedel = _dbcontext.Employees.Where(empid => empid.Id == id).FirstOrDefault();
        if (employeedel == null) return "Employee does not exists";

        _dbcontext.Employees.Remove(employeedel);
        await _dbcontext.SaveChanges();
        return "Employee details deleted modified";
    }
}

As shown below register Employee repository as a service in the ConfigureServices method of Startup class

services.AddTransient<IEmployeeRepository, EmployeeRepository>();

Repository helps in better testing of the code. Since repository is passed as service till database is ready we can create a dummy repository service for simulation of CRUD operations. Also we can pass different repository implementation based of environments. If you want to read more about how to handle multiple environment you can read my article on Configuring multiple ASP.NET Core hosting environment

Add Employee controller

Here is the code for the Employee controller which has been added to expose the CRUD operations for the Employee entity as a API. Employee Repository has been passed as constructor parameter using dependency injection. Implementation have been added by calling the methods in repository class. I have not covered validations here but before calling repository method input should be validated.

[Route("api/[controller]")]
[ApiController]
public class EmployeeController : ControllerBase
{
    private IEmployeeRepository _employeerepository;
    public EmployeeController(IEmployeeRepository employeerepository)
    {
        _employeerepository = employeerepository;
    }

    [HttpPost]
    [Route("Create")]
    public async Task<ActionResult> create([FromBody] Employee employee)
    {
        int empid = await _employeerepository.Create(employee);
        return Ok(empid);
    }

    [HttpGet]
    [Route("GetAll")]
    public async Task<ActionResult> GetAll()
    {
        var employees = await _employeerepository.GetAll();
        return Ok(employees);
    }

    [HttpGet]
    [Route("GetById/{id}")]
    public async Task<ActionResult> GetById(int id)
    {
        var employee = await _employeerepository.GetById(id);
        return Ok(employee);
    }

    [HttpPut]
    [Route("Update/{id}")]
    public async Task<IActionResult> Update(int id, Employee employee)
    {
        string resp = await _employeerepository.Update(id, employee);
        return Ok(resp);
    }

    [HttpDelete]
    [Route("Delete/{id}")]
    public async Task<IActionResult> Delete(int id)
    {
        var resp = await _employeerepository.Delete(id);
        return Ok(resp);
    }
}

Let’s run & test the code

Will be using postman to test the code.

Create – request & response. Here we can see that we are sending a post HTTP request for creating along with Employee object in the body in JSON format & in response we get employee Id

EF Core - Create Request

GetAll – request & response. Here we are sending a get HTTP request without any parameters & in response we get all the employees present in database.

EF Core - GetAll Request

Entity Framework Conventions

We saw that we just added the entity class for Employee and the table was created for this entity without specifying any metadata for the database or table. This is due to the fact that the entity framework does this based on the default conventions or assumptions it follows.

  • DbSet property name is used for table name.
  • Entity class property name is used for column name.
  • Entity class properties with name ID or classnameID are assumed as primary key.

You can override these conventions by specifying your own details for the table name, column name, primary key, and foreign key details.

Modifying the database with Annotations

Entity class can be modified to specify the metadata for the table being created for entity i.e. it will override the default conventions used for migrations. Data Annotations Attributed available in namespace “System.ComponentModel.DataAnnotations” to specify the column properties for table.

public class Employee
{
    public int Id { get; set; }
        
    [Required]
    [StringLength(60)]
    public string FirstName { get; set; }

    [StringLength(60)]
    public string MiddleName { get; set; }

    [StringLength(60)]
    public string LastName { get; set; }

    [Required]
    public string Designation { get; set; }

    [Required]
    public double Salary { get; set; }
}
EF Core - Modified Database

Entity Framework Fluent API can also be used to configure DbContext classes to override conventions.

Summary

We covered how to implement Entity Framework Core in ASP.NET Web API with the code-first approach. I have even posted a video of the implementation.

One thing to keep in mind is that the entity framework doesn’t fit in all the scenarios so please do your research well before deciding to implement it in your project.

Referenceshttps://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/intro?view=aspnetcore-3.1

Source code download

https://github.com/procodeguide/EFCore.Sample
  1. What is entity framework core?

    It is an open-source object-relational mapper (ORM) built over ADO.NET and an official data access platform from Microsoft.W

  2. Which databases are supported with Entity framework?

    Entity framework core can work with wide variety of databases. Microsoft provides rich providers for SQL Server & SQLite and there are many other third party providers some commercial and some from community.

  3. Is entity framework code asynchronous ?

    Asynchronous programming is the default mode for ASP.NET Core and Entity Framework Core.

Hope you found this article useful
Buy me a coffeeBuy me a coffee
Leave a Reply

Leave a Reply

Your email address will not be published. Required fields are marked *