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.
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.
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
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
So, let’s move and create a folder name as ‘Model’ and create a Model class as ‘TblCustomer‘ in with the following properties.
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; } } }
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.
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.
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,
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.
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.
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.
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.
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:
PUT Method:
POST Method:
DELETE Method:
Helper Method:
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); } } }
Now build project and take a look at the browser. You can see swagger page. now let’s call our Api.
POST–api/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]" }
{ "customerId": 1, "customerName": "Mark", "customerNumber": "12346679", "customerEmail": "[email protected]" }
GET: api/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(); }
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]" } ]
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; }
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(); }
{ "customerId": 1, "customerName": "Mark New Name", "customerNumber": "9989898989", "customerEmail": "[email protected]" }
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(); }
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.