In this article, we will learn how to perform CRUD operations in ASP.NET Core Web API using the Entity Framework Code-First approach.

I will provide a step-by-step tutorial explaining how to perform CRUD operations in ASP.NET Core Web API using the Entity Framework Code-First approach.

We can divide the complete post into below step

  1. Creating  Core Web API Project in VS
  2. Install Nuget Packages in our project for Entity Framework
  3. Creating Model Classes & Configuring EF Core
  4. Setup database connection string in appsettings.json
  5. Creating the Database from Code Using Migrations
  6. Creating an API Controller
  7. Perform the Testing on the API End Points in Swagger

Code-First Approach

The Entity Framework introduced the Code-First approach. Some .NET developers favor working with the Designer in Code EF or database first approach while some just prefer work with their code.

Code-First Approach

At Code First, we focus on the domain of our project and start creating model classes for your domain entity instead of designing the database first. we create model classes that match our database design. It means to say that in the code first approach we create the database from model classes i.e Code First modeling approach create a database that doesn’t exist in our database and Code First will create it first.

If you want to use the database first approach read below article

Create ASP.NET Core  Web API Project

  1. Open Visual Studio ,Click to >Create a new Project>Asp .Net Core Web Application

Creatiing Core Api Project

Creeating Core Project

Install Nuget Packages in our Web Api Core project

Now we have running build project and You can check this by using F5 to run the API. It will open the swagger page for testing the API.

Now we need to install some Entity Framework core packages from the NuGet package manager to perform database Crud operations from C# code.

First Package- Microsoft.EntityFrameworkCore.SqlServer

This NuGet package provides classes for Entity Framework Core to connect to SQL Server for database operations.

Second Package- Microsoft.EntityFrameworkCore.Tools

This Nuget package will support us to work with database-related activity like adding migration for database, script migration, DB context, update Object database, etc.

So we have created a Core API application and installed the required Entity Framework Core Nuget packages that need for Code First Migration, to use Entity Framework Core features to work with SQL Server Database

Creating Model Classes & Configuring EF Core

So, let’s move and create a folder name as ‘Model’ and create a Model class as ‘TblCustomer‘ in with the following properties.

1

The class above defines the class TblCustomer with some properties. Additionally, we have decorated the CustomerId property with Key and DatabaseGenerated attributes because we will be turning this class into a database table and the column CustomerId will serve as the primary key Column with the auto-incremented identity that means you can say that we declaring CustomerId as primary-key with Identity.

 public class TblCustomer
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long CustomerId { get; set; }
    public string CustomerName { get; set; }
    public string CustomerNumber { get; set; }
    public string CustomerEmail { get; set; }
    }

As the next step, We will create another class inside the Model folder as ‘CustomerDbContext’ that will inherit to DbContext class and define the database connection and register the context in our application.

This class will contain all the information which is responsible for creating and updating the tables in our database.

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace CrudCodeFirst.Model
{
    public class CustomerDbContext : DbContext
    {
    public CustomerDbContext(DbContextOptions options) : base(options)
        {
        }
        public DbSet<TblCustomer> TblCustomer { get; set; }
    }
}

2

As we know that in the EF Code First approach, first We need to write the Model classes, and on the basis of these Model classes our database tables are generated in the database.

Setup database connection string in appsettings.json

To create these tables in the database let’s define the database connection in the appsettings.json file.

{
    "Logging": {
    "LogLevel": {
    "Default": "Warning"
    }
  },
    "ConnectionStrings": {

    "myconn": "server=SQLEXPRESS01;initial catalog=CustomerDb;user id=***;password=****;multipleactiveresultsets=True;"
  },
    "AllowedHosts": "*"
}

To use the database connection string, register our context in the Startup.cs class as follows.

public void ConfigureServices(IServiceCollection services)
        {

            services.AddControllers();
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "CrudCodeFirst", Version = "v1" });
            });
            services.AddDbContext<CustomerDbContext>(item => item.UseSqlServer(Configuration.GetConnectionString("myconn")));
        }

So, the next step is to generate the database using Entity Framework Core Migrations.
Open Package Manager Console from the Tools Menu and run the following command in the Package Manager console: ‘add-migration MigrationName’

let’s run this command and see what happens. In the Nuget Package Manager Console, just type the ‘add-migration DataBaseSetup” command and press Enter.

3

4

This migration command creates a folder name as ‘Migrations’ in our web API project and creates the class with the name [MigrationName] as which we provided while running add migration command.
Here you can see the table structure based on your Model TblCustomer,

5

 

using Microsoft.EntityFrameworkCore.Migrations;

namespace CrudCodeFirst.Migrations
{
    public partial class DataBaseSetup : Migration
    {
    protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.CreateTable(
                name: "TblCustomer",
                columns: table => new
                {
                    CustomerId = table.Column<long>(type: "bigint", nullable: false)
                        .Annotation("SqlServer:Identity", "1, 1"),
                    CustomerName = table.Column<string>(type: "nvarchar(max)", nullable: true),
                    CustomerNumber = table.Column<string>(type: "nvarchar(max)", nullable: true),
                    CustomerEmail = table.Column<string>(type: "nvarchar(max)", nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_TblCustomer", x => x.CustomerId);
                });
        }

    protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropTable(
                name: "TblCustomer");
        }
    }
}

Now We have created the migration script for creating the database and table. and we know that we didn’t create the database and tables in the SQL server.
So, let’s run the migration script to create the database and tables. execute command ‘update-database‘ in the package manager console.

6

When the command executes successfully, open your SQL Server Management Studio, you can able see the database, table, and Entity Framework Migration history table as follows.

7

Create a API Controller

Now Let’s Create a API Controller for Performaing crud operations in our table, So, Let’s add a new API controller name as TblCustomersController.

  • Right-click on controller folder in the Project
  • Add>controller> choose Api Controller from left side
  • Select Empty controller

Creating Empty Controller

Or create a controller using entity framework using template

you can also choose read/write action using entity framework, it will create all necessary endpoints for you. using a read/write template you don’t need to write the code manually. it will auto generate the code.
My suggestion is that for learning purposes you should create an empty controller and write code yourself instead of autogenerated code.

  • Right-click on controller folder in the Project
  • Add>controller> choose Api Controller from left side
  • Select Api controller with actions using entity framework
  • Choose Model Class
  • Select DbContext
  • Give Controller and then click on Add Button

Create Autogenrated Api

TblCustomersController.cs

This C# ASP.NET Core API controller, named TblCustomersController, is responsible for handling CRUD (Create, Read, Update, Delete) operations for a TblCustomer entity. Here's a breakdown of the code:

Constructor and Dependency Injection:

The constructor injects an instance of CustomerDbContext into the controller. This is the database context used to interact with the database.

GET Methods:

  • GetTblCustomer(): Handles HTTP GET requests to retrieve all customers. It asynchronously returns a list of all TblCustomer entities fetched from the database context.
  • GetTblCustomer(long id): Handles HTTP GET requests to retrieve a specific customer by their ID. It asynchronously fetches the customer with the provided ID from the database context. If the customer doesn't exist, it returns a NotFound response.

PUT Method:

  • PutTblCustomer(long id, TblCustomer tblCustomer): Handles HTTP PUT requests to update a specific customer by their ID. It expects the ID of the customer to update and the updated customer object (tblCustomer). It validates whether the provided ID matches the customer's ID. If not, it returns a BadRequest response. If the ID matches, it updates the customer's state in the database context and saves the changes. If the customer doesn't exist, it returns a NotFound response.

POST Method:

  • PostTblCustomer(TblCustomer tblCustomer): Handles HTTP POST requests to create a new customer. It expects a TblCustomer object (tblCustomer) in the request body. It validates the model state and adds the new customer to the database context. Upon successful insertion, it returns a CreatedAtAction response with the newly created customer's details.

DELETE Method:

  • DeleteTblCustomer(long id): Handles HTTP DELETE requests to delete a specific customer by their ID. It expects the ID of the customer to delete. It retrieves the customer with the given ID from the database context. If the customer doesn't exist, it returns a NotFound response. Otherwise, it removes the customer from the database context and saves the changes. It returns a NoContent response upon successful deletion.

Helper Method:

  • TblCustomerExists(long id): Checks if a customer with the given ID exists in the database context.

This controller provides endpoints to perform CRUD operations on the TblCustomer entity, interacting with the database through the Entity Framework database context.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using CrudCodeFirst.Model;

namespace CrudCodeFirst.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class TblCustomersController : ControllerBase
    {
    private readonly CustomerDbContext _context;

    public TblCustomersController(CustomerDbContext context)
        {
            _context = context;
        }

    // GET: api/TblCustomers
        [HttpGet]
    public async Task<ActionResult<IEnumerable<TblCustomer>>> GetTblCustomer()
        {
    return await _context.TblCustomer.ToListAsync();
        }

    // GET: api/TblCustomers/5
        [HttpGet("{id}")]
    public async Task<ActionResult<TblCustomer>> GetTblCustomer(long id)
        {
    var tblCustomer = await _context.TblCustomer.FindAsync(id);

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

    return tblCustomer;
        }

    // PUT: api/TblCustomers/5
    // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
        [HttpPut("{id}")]
    public async Task<IActionResult> PutTblCustomer(long id, TblCustomer tblCustomer)
        {
    if (id != tblCustomer.CustomerId)
            {
    return BadRequest();
            }

            _context.Entry(tblCustomer).State = EntityState.Modified;

    try
            {
    await _context.SaveChangesAsync();
            }
    catch (DbUpdateConcurrencyException)
            {
    if (!TblCustomerExists(id))
                {
    return NotFound();
                }
    else
                {
    throw;
                }
            }

    return NoContent();
        }

    // POST: api/TblCustomers
        
        [HttpPost]
    public async Task<ActionResult<TblCustomer>> PostTblCustomer(TblCustomer tblCustomer)
        {
            if (!ModelState.IsValid) { return BadRequest(ModelState); }
            _context.TblCustomer.Add(tblCustomer);
    await _context.SaveChangesAsync();

    return CreatedAtAction("GetTblCustomer", new { id = tblCustomer.CustomerId }, tblCustomer);
        }

    // DELETE: api/TblCustomers/5
        [HttpDelete("{id}")]
    public async Task<IActionResult> DeleteTblCustomer(long id)
        {
    var tblCustomer = await _context.TblCustomer.FindAsync(id);
    if (tblCustomer == null)
            {
    return NotFound();
            }

            _context.TblCustomer.Remove(tblCustomer);
    await _context.SaveChangesAsync();

    return NoContent();
        }

    private bool TblCustomerExists(long id)
        {
    return _context.TblCustomer.Any(e => e.CustomerId == id);
        }
    }
}

Perform Testing with Help of Swagger or you can use postman also

Now build project and take a look at the browser. You can see swagger page. now let’s call our Api.

Api Swagger

1. Create Customer Object in database

POSTapi/TblCustomers
The PostTblCustomer action method will handle HTTP POST requests and make an entry in the database table.

// POST: api/TblCustomers
        [HttpPost]
    public async Task<ActionResult<TblCustomer>> PostTblCustomer(TblCustomer tblCustomer)
        {
    if (!ModelState.IsValid)
            {
    return BadRequest(ModelState);
            }
            _context.TblCustomer.Add(tblCustomer);
    await _context.SaveChangesAsync();

    return CreatedAtAction("GetTblCustomer", new { id = tblCustomer.CustomerId }, tblCustomer);
        }


The `PostTblCustomer` action method handles HTTP POST requests and inserts an entry into the database table.

In the `PostTblCustomer` method, we first validate the model using `ModelState.IsValid`. This ensures that the `TblCustomer` object contains all the required information. If this condition is not met, a BadRequest response is returned. If the `TblCustomer` model, i.e., the data model, is valid, we add the `TblCustomer` using the Entity Framework context and return a CreatedAtAction status response.

Request body

{
  
    "customerName": "Mark",
    "customerNumber": "12346679",
    "customerEmail": "[email protected]"
}
Response body
{
    "customerId": 1,
    "customerName": "Mark",
    "customerNumber": "12346679",
    "customerEmail": "[email protected]"
}
  • Let’s do test on swagger, Click Post tab,then click on Try it Out Button
  • Input Body parameter and click on the excute button

Post Api

2. Get All Customers

GETapi/GetTblCustomer

The following GetTblCustomer() action method in TblCustomer class returns all the Customer from the database using Entity Framework.

// GET: api/TblCustomers
        [HttpGet]
    public async Task<ActionResult<IEnumerable<TblCustomer>>> GetTblCustomer()
        {
    return await _context.TblCustomer.ToListAsync();
        }
  • Let’s do test on swagger, Click Get /api/TblCustomers tab,then click on Try it Out Button
  • Click on the excute button

Get Api Testing

It will return all customer records in the Tblcustomer table, right now we only have one record that’s why it returns only one object.
Response body

[
  {
    "customerId": 1,
    "customerName": "Mark",
    "customerNumber": "12346679",
    "customerEmail": "[email protected]"
  }
]

3. Get Customer by Id

GET: api/TblCustomers/1
It will return all Customer with id=1 in the database

As you can see in the code below, the `GetTblCustomer()` method retrieves a customer by their ID using EF. If no customer exists in the database table, it returns a 404 NotFound response; otherwise, it returns a 200 OK response with the customer data.

The NotFound() and Ok() methods defined in the Tblcustomer return 404 and 200 responses, respectively, according to our conditions.

 // GET: api/TblCustomers/5
        [HttpGet("{id}")]
    public async Task<ActionResult<TblCustomer>> GetTblCustomer(long id)
        {
    var tblCustomer = await _context.TblCustomer.FindAsync(id);

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

    return tblCustomer;
        }
  • Let’s do test on swagger, Click Get /api/TblCustomers/{id} tab,then click on Try it Out Button
  • Enter Customer Id for find record,Click on the excute button

Get By Id

Return the database record with Id=1

Response body

{
    "customerId": 1,
    "customerName": "Mark",
    "customerNumber": "12346679",
    "customerEmail": "[email protected]"
}

4. PUT/api/TblCustomers/1

The PUT method is utilized to update the TblCustomer table in the database. You only need to pass the TblCustomer object in the request body, and in response, you will receive the updated TblCustomer record.

The `PutTblCustomer()` action method in our TblCustomerController is used to update an existing Customer record in the database using Entity Framework.

[HttpPut("{id}")]
    public async Task<IActionResult> PutTblCustomer(long id, TblCustomer tblCustomer)
        {
    if (id != tblCustomer.CustomerId)
            {
    return BadRequest();
            }

            _context.Entry(tblCustomer).State = EntityState.Modified;

    try
            {
    await _context.SaveChangesAsync();
            }
    catch (DbUpdateConcurrencyException)
            {
    if (!TblCustomerExists(id))
                {
    return NotFound();
                }
    else
                {
    throw;
                }
            }

    return NoContent();
        }
  • Let's test it on Swagger. Click on the PUT `/api/TblCustomers/{id}` tab, then click on the 'Try it Out' button. Enter the Customer ID for which you want to update the record, let's say for example, Id=1. Input the updated values, then click on the 'Execute' button. This will update the customer record with Id=1.

Response Put Api

Request body

{
    "customerId": 1,
    "customerName": "Mark New Name",
    "customerNumber": "9989898989",
    "customerEmail": "[email protected]"
}

5. DELETE Doctor by Id

DELETE:/api/TblCustomers/1
It will delete the Customer with id=1 in the database

DeleteTblCustomer() action method in our TblCustomerController use to delete an existing Customer record in the database using Entity Framework.

// DELETE: api/TblCustomers/5
        [HttpDelete("{id}")]
    public async Task<IActionResult> DeleteTblCustomer(long id)
        {
    var tblCustomer = await _context.TblCustomer.FindAsync(id);
    if (tblCustomer == null)
            {
    return NotFound();
            }

            _context.TblCustomer.Remove(tblCustomer);
    await _context.SaveChangesAsync();

    return NoContent();
        }
  • Let’s do test on swagger, Click DELETE /api/TblCustomers/{id} tab,then click on Try it Out Button
  • Enter Customer Id for deleting record,Click on the excute button

Delete Record

So, in this post, we have seen how to perform creating ASP.NET Core Web API using Entity Framework Core Code First approach, if you have any queries or doubts, please comment.