CRUD Operations In ASP.NET Core Using Entity Framework Core Code First

Introduction

This article introduces how to perform the Create, Read, Update, and Delete (CRUD) operations in ASP.NET Core, using Entity Framework Core. 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. I would like to recommend the following the article Overview Of ASP.NET Core so that we start development for this sample application in ASP.NET Core. We will create a single entity Customer to perform the CRUD operations.

Create Database

First, let's install the Entity Framework Core in our application. As we use SQL Server, install the package for SQL Server database provider. To install database provider, follow the below steps.

  • Tools - NuGet Package Manager - Package Manager Console
  • Run PM> Install-Package Microsoft.EntityFrameworkCore.SqlServer

When we install a package in ASP.NET Core application, then the package installation occurs in the background. We see "(Restoring...)" appeared next to References in Solution Explorer while the installation occurs.

We also use Entity Framework Core as an Object Relationship Mapper (ORM) to perform the CRUD operations. Let's install the Entity Framework Core Tool to maintain the database, using the following procedure.

  • Run PM> Install-Package Microsoft.EntityFrameworkCore.Tools –Pre.
  • Open project.json file.
  • Locate the tools section and add the ef command as shown below.
    1. "tools": {  
    2.     "Microsoft.EntityFrameworkCore.Tools""1.0.0-preview2-final",  
    3.     "BundlerMinifier.Core""2.0.238",  
    4.     "Microsoft.AspNetCore.Razor.Tools""1.0.0-preview2-final",  
    5.     "Microsoft.AspNetCore.Server.IISIntegration.Tools""1.0.0-preview2-final"  
    6.   }  

Now, create two entities - the BaseEntity class that has common properties that will be inherited by each entity, and the Customer. Let's see each entity. The following is a code snippet for the BaseEntity class.

  1. using System;  
  2.   
  3. namespace CRUDApplication.DbEntities  
  4. {  
  5.     public class BaseEntity  
  6.     {  
  7.         public Int64 Id { get; set; }  
  8.         public DateTime AddedDate { get; set; }  
  9.         public DateTime ModifiedDate { get; set; }  
  10.         public string IPAddress { get; set; }  
  11.     }  
  12. }  
Now, create a Customer entity under the DbEntities folder which inherits from the BaseEntity class. The following is a code for Customer entity.
  1. namespace CRUDApplication.DbEntities  
  2. {  
  3.     public class Customer:BaseEntity  
  4.     {  
  5.         public string FirstName { get; set; }  
  6.         public string LastName { get; set; }  
  7.         public string Email { get; set; }  
  8.         public string MobileNo { get; set; }  
  9.     }  
  10. }  
Now, let's define the configuration for the Customer entity that will be used when the database table will be created by the entity. The following is the code for Customer mapping entity (CustomerMap.cs).
  1. using Microsoft.EntityFrameworkCore.Metadata.Builders;  
  2.   
  3. namespace CRUDApplication.DbEntities  
  4. {  
  5.     public class CustomerMap   
  6.     {  
  7.         public CustomerMap(EntityTypeBuilder<Customer> entityBuilder)  
  8.         {  
  9.             entityBuilder.HasKey(t => t.Id);              
  10.             entityBuilder.Property(t => t.FirstName).IsRequired();  
  11.             entityBuilder.Property(t => t.LastName).IsRequired();  
  12.             entityBuilder.Property(t => t.Email).IsRequired();  
  13.             entityBuilder.Property(t => t.MobileNo).IsRequired();             
  14.         }  
  15.     }  
  16. }  
The EntityTypeBuilder<T> is an important class that allows configuration to be performed for an entity type in a model. This is done using the modelbuilder in an override of the OnModelCreating method. The Constructor of the CustomerMap class uses the Fluent API to map and configure properties in the table. So let's see each method used in the constructor one-by-one. 
  1. HasKey()
    The Haskey() method configures a primary key on table.

  2. Property()
    The Property method configures attributes for each property belonging to an entity or complex type. It is used to obtain a configuration object for a given property. The options on the configuration object are specific to the type being configured.

Now, it’s time to define context class. The ADO.NET Entity Framework Code First development approach requires us to create a data access context class that inherits from the DbContext class so we create a context class CRUDContext (CRUDContext.cs) class. In this class, we override the OnModelCreating() method. This method is called when the model for a context class (CRUDContext) 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.

  1. using Microsoft.EntityFrameworkCore;  
  2.   
  3. namespace CRUDApplication.DbEntities  
  4. {  
  5.     public class CRUDContext:DbContext  
  6.     {  
  7.         public CRUDContext(DbContextOptions<CRUDContext> options) : base(options)  
  8.         {  
  9.         }  
  10.         protected override void OnModelCreating(ModelBuilder modelBuilder)  
  11.         {  
  12.             base.OnModelCreating(modelBuilder);  
  13.             new CustomerMap(modelBuilder.Entity<Customer>());  
  14.         }  
  15.     }  
  16. }  
As the concept of dependency injection is central to the ASP.NET Core application, so we register our context to dependency injection during the application start up. Once we register CRUDContext context as a service to dependency injection, then provide it via constructor to MVC controller. In order for our MVC controllers to make use of CRUDContext, we are going to register it as a service. 
  1. Open the appsettings.json file and define connection string here.
    1. {  
    2.   "ConnectionStrings": {  
    3.     "DefaultConnection""Data Source=ADMIN\\SQLEXPRESS;Initial Catalog=ECommerceDb;User ID=sa; Password=*****"  
    4.   },  
    5.   "Logging": {  
    6.     "IncludeScopes"false,  
    7.     "LogLevel": {  
    8.       "Default""Debug",  
    9.       "System""Information",  
    10.       "Microsoft""Information"  
    11.     }  
    12.   }  
    13. }  
    It stores application level settings such as connection string, SMTP etc. It’s similar to web.config file in ASP.NET.

  2. Open the Startup.cs file and following using statements at the start of the file.
    1. using Microsoft.EntityFrameworkCore;  
    2. using CRUDApplication.DbEntities;  
  3. Now, we can use the AddDbContext method to register it as a service. Locate the ConfigureServices method and add the lines of code for register it to dependency injection as per following code snippet.
    1. public void ConfigureServices(IServiceCollection services)  
    2.         {  
    3.             services.AddMvc();  
    4.             services.AddDbContext<CRUDContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));  
    5.         }  
    Now we have created model so time to create database using migration.

    • 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 CustomerController 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 CRUDContext class instance then we inject it in the controller's constructor to get its object. The following is a code snippet for the CustomerController.

  1. using CRUDApplication.DbEntities;  
  2. using CRUDApplication.Models;  
  3. using Microsoft.AspNetCore.Http;  
  4. using Microsoft.AspNetCore.Mvc;  
  5. using System;  
  6. using System.Collections.Generic;  
  7. using System.Linq;  
  8.   
  9. namespace CRUDApplication.Controllers  
  10. {  
  11.     public class CustomerController : Controller  
  12.     {  
  13.         private CRUDContext context;  
  14.   
  15.         public CustomerController(CRUDContext context)  
  16.         {  
  17.             this.context = context;  
  18.         }  
  19.         [HttpGet]  
  20.         public IActionResult Index()  
  21.         {  
  22.             IEnumerable<CustomerViewModel> model = context.Set<Customer>().ToList().Select(s => new CustomerViewModel  
  23.             {  
  24.                 Id= s.Id,  
  25.                 Name = $"{s.FirstName} {s.LastName}",  
  26.                 MobileNo = s.MobileNo,  
  27.                 Email = s.Email  
  28.             });  
  29.             return View("Index", model);  
  30.         }  
  31.   
  32.         [HttpGet]  
  33.         public IActionResult AddEditCustomer(long? id)  
  34.         {  
  35.             CustomerViewModel model = new CustomerViewModel();  
  36.             if (id.HasValue)  
  37.             {  
  38.                 Customer customer = context.Set<Customer>().SingleOrDefault(c => c.Id == id.Value);  
  39.                 if (customer != null)  
  40.                 {  
  41.                     model.Id = customer.Id;  
  42.                     model.FirstName = customer.FirstName;  
  43.                     model.LastName = customer.LastName;  
  44.                     model.MobileNo = customer.MobileNo;  
  45.                     model.Email = customer.Email;  
  46.                 }  
  47.             }  
  48.             return PartialView("~/Views/Customer/_AddEditCustomer.cshtml", model);  
  49.         }  
  50.   
  51.         [HttpPost]  
  52.         public ActionResult AddEditCustomer(long? id, CustomerViewModel model)  
  53.         {  
  54.             try  
  55.             {  
  56.                 if (ModelState.IsValid)  
  57.                 {  
  58.                     bool isNew = !id.HasValue;  
  59.                     Customer customer = isNew ? new Customer  
  60.                     {  
  61.                         AddedDate = DateTime.UtcNow  
  62.                     } : context.Set<Customer>().SingleOrDefault(s => s.Id == id.Value);  
  63.                     customer.FirstName = model.FirstName;  
  64.                     customer.LastName = model.LastName;  
  65.                     customer.MobileNo = model.MobileNo;  
  66.                     customer.Email = model.Email;  
  67.                     customer.IPAddress = Request.HttpContext.Connection.RemoteIpAddress.ToString();  
  68.                     customer.ModifiedDate = DateTime.UtcNow;  
  69.                     if (isNew)  
  70.                     {  
  71.                         context.Add(customer);  
  72.                     }  
  73.                     context.SaveChanges();  
  74.                 }  
  75.             }  
  76.             catch (Exception ex)  
  77.             {  
  78.                 throw ex;  
  79.             }  
  80.             return RedirectToAction("Index");  
  81.         }  
  82.   
  83.         [HttpGet]  
  84.         public IActionResult DeleteCustomer(long id)  
  85.         {  
  86.             Customer customer = context.Set<Customer>().SingleOrDefault(c => c.Id == id);  
  87.             CustomerViewModel model = new CustomerViewModel  
  88.             {  
  89.                 Name = $"{customer.FirstName} {customer.LastName}"  
  90.             };  
  91.             return PartialView("~/Views/Customer/_DeleteCustomer.cshtml", model);  
  92.         }  
  93.         [HttpPost]  
  94.         public IActionResult DeleteCustomer(long id, FormCollection form)  
  95.         {  
  96.             Customer customer = context.Set<Customer>().SingleOrDefault(c => c.Id == id);  
  97.             context.Entry(customer).State = Microsoft.EntityFrameworkCore.EntityState.Deleted;  
  98.             context.SaveChanges();  
  99.             return RedirectToAction("Index");  
  100.         }  
  101.     }  
  102. }  
We can notice that the Controller takes a CRUDContext as a constructor parameter. ASP.NET dependency injection will take care of passing an instance of CRUDContext into our controller. The controller is developed to handle CURD operation requests for a Customer entity. Now, let's develop the user interface for the CRUD operations. We develop it for the views for adding and editing a customer, a customer listing, customer deletion. Let's see each one by one.

Customer List View

This is the first view when the application is accessed or the entry point of the application is executed. It shows the customer listing as in Figure 1. We display customer data in tabular format and on this view we create links to add a new customer, edit a customer and delete a customer. This view is an index view and the following is a code snippet for index.cshtml under the Customer folder of Views.
  1. @model IEnumerable<CRUDApplication.Models.CustomerViewModel>  
  2. @using CRUDApplication.Models  
  3. @using CRUDApplication.Code  
  4.   
  5. <div class="top-buffer"></div>  
  6. <div class="panel panel-primary">  
  7.     <div class="panel-heading panel-head">Customers</div>  
  8.     <div class="panel-body">  
  9.         <div class="btn-group">  
  10.             <a id="createEditCustomerModal" data-toggle="modal" asp-action="AddEditCustomer" data-target="#modal-action-customer" class="btn btn-primary">  
  11.                 <i class="glyphicon glyphicon-plus"></i>  Add Customer  
  12.             </a>  
  13.         </div>  
  14.         <div class="top-buffer"></div>  
  15.         <table class="table table-bordered table-striped table-condensed">  
  16.             <thead>  
  17.                 <tr>  
  18.                     <th>Name</th>                      
  19.                     <th>Email</th>  
  20.                     <th>Mobile No</th>  
  21.                     <th>Action</th>  
  22.                 </tr>  
  23.             </thead>  
  24.             <tbody>  
  25.                 @foreach (var item in Model)  
  26.                 {  
  27.                     <tr>  
  28.                         <td>@Html.DisplayFor(modelItem => item.Name)</td>  
  29.                         <td>@Html.DisplayFor(modelItem => item.Email)</td>  
  30.                         <td>@Html.DisplayFor(modelItem => item.MobileNo)</td>                         
  31.                         <td>  
  32.                             <a id="editCustomerModal" data-toggle="modal" asp-action="AddEditCustomer" asp-route-id= "@item.Id" data-target="#modal-action-customer"   
  33.                                class="btn btn-info">  
  34.                                 <i class="glyphicon glyphicon-pencil"></i>  Edit  
  35.                             </a>  
  36.                             <a id="deleteCustomerModal" data-toggle="modal" asp-action="DeleteCustomer" asp-route-id= "@item.Id" data-target="#modal-action-customer" class="btn btn-danger">  
  37.                                 <i class="glyphicon glyphicon-trash"></i>  Delete  
  38.                             </a>  
  39.                         </td>  
  40.                     </tr>  
  41.                 }  
  42.             </tbody>  
  43.         </table>  
  44.     </div>  
  45. </div>  
  46. @Html.Partial("_Modal"new BootstrapModel { ID = "modal-action-customer", AreaLabeledId = "modal-action-customer-label", Size = ModalSize.Medium })  
  47. @section scripts  
  48. {  
  49.     <script src="~/js/customer-index.js" asp-append-version="true"></script>  
  50. }  
When we run the application and call the index() action with a HttpGet request, then we get all the customers listed in the UI as in Figure 1. This UI has options for CRUD operations.

Customer Listing UI
Figure 1: Customer Listing UI

Create / Edit Customer View

We create a common view to create and edit a customer so we create a single customer view model. The following code snippet for CustomerViewModel.cs.
  1. using System.ComponentModel.DataAnnotations;  
  2.   
  3. namespace CRUDApplication.Models  
  4. {  
  5.     public class CustomerViewModel  
  6.     {  
  7.         public long Id { get; set; }  
  8.         [Display(Name="First Name")]  
  9.         public string FirstName { get; set; }  
  10.         [Display(Name = "Last Name")]  
  11.         public string LastName { get; set; }  
  12.         public string Name { get; set; }   
  13.         public string Email { get; set; }  
  14.         [Display(Name = "Mobile No")]  
  15.         public string MobileNo { get; set; }  
  16.     }  
  17. }  
We show form in bootstrap modal popup and submit using ajax post; that’s why we create a javascript file which contains method for removing loaded data.
  1. (function ($) {  
  2.     function Customer() {  
  3.         var $this = this;  
  4.   
  5.         function initilizeModel() {             
  6.             $("#modal-action-customer").on('loaded.bs.modal'function (e) {                 
  7.                 }).on('hidden.bs.modal'function (e) {                     
  8.                     $(this).removeData('bs.modal');  
  9.                 });              
  10.         }         
  11.         $this.init = function () {  
  12.             initilizeModel();  
  13.         }  
  14.     }  
  15.     $(function () {  
  16.         var self = new Customer();  
  17.         self.init();          
  18.     })  
  19. }(jQuery))  
Now, define a create/edit customer partial view. The following is the code snippet for _AddEditCustomer.cshtml.
  1. @model CRUDApplication.Models.CustomerViewModel  
  2. @using CRUDApplication.Models  
  3.   
  4. <form asp-action="AddEditCustomer" role="form">  
  5.     @await Html.PartialAsync("_ModalHeader"new ModalHeader { Heading = String.Format("{0} Customer", @Model.Id == 0 ? "Add" : "Edit") })  
  6.      
  7.     <div class="modal-body form-horizontal">  
  8.         <div class="form-group">  
  9.             <label asp-for="FirstName" class="col-lg-3 col-sm-3 control-label"></label>             
  10.             <div class="col-lg-6">  
  11.                 <input asp-for="FirstName" class="form-control" />                  
  12.             </div>  
  13.         </div>  
  14.         <div class="form-group">  
  15.             <label asp-for="LastName" class="col-lg-3 col-sm-3 control-label"></label>    
  16.             <div class="col-lg-6">  
  17.                 <input asp-for="LastName" class="form-control" />                                 
  18.             </div>  
  19.         </div>  
  20.         <div class="form-group">  
  21.             <label asp-for="Email" class="col-lg-3 col-sm-3 control-label"></label>  
  22.             <div class="col-lg-6">  
  23.                 <input asp-for="Email" class="form-control" />  
  24.             </div>  
  25.         </div>  
  26.         <div class="form-group">  
  27.             <label asp-for="MobileNo" class="col-lg-3 col-sm-3 control-label"></label>   
  28.             <div class="col-lg-6">  
  29.                 <input asp-for="MobileNo" class="form-control" />   
  30.             </div>  
  31.         </div>          
  32.     </div>  
  33.   @await Html.PartialAsync("_ModalFooter"new ModalFooter { })  
  34. </form>  
Now, run the application and click on Edit button of listing which calls AddEditCustomer action method, then we get the UI as in Figure 2 to edit a customer.

Edit a Customer UI
Figure 2: Edit a Customer UI

Delete A Customer

To delete a customer, we follow the process of clicking on the Delete button that exists in the Customer listing data then a modal popup shows to ask “Are you want to delete xxx?” after clicking on the Delete button that exists in the popup view such as in Figure 3 then it makes a HttpPost request that calls the DeleteCustomer() action method and deletes the customer. The following is a code snippet for _DeleteCustomer.cshtml.
  1. @model CRUDApplication.Models.CustomerViewModel  
  2. @using CRUDApplication.Models  
  3.   
  4. @using (Html.BeginForm())  
  5. {  
  6.     @Html.Partial("_ModalHeader"new ModalHeader { Heading = "Delete Customer" })  
  7.   
  8.     <div class="modal-body form-horizontal">  
  9.         Are you want to delete @Model.Name?  
  10.     </div>  
  11.     @Html.Partial("_ModalFooter"new ModalFooter { SubmitButtonText = "Delete" })  
  12. }  
Now, run the application and click on Delete button of listing which call DeleteCustomer action method, then we get the UI as in Figure 3 to delete a customer.

Delete Confirmation
Figure 3: Delete Confirmation

Download

You can download complete source code from TechNet Gallery using following links. 
  1. CRUD Operations in ASP.NET Core and Entity Framework Core
  2. Rating Star Application in ASP.NET Core
  3. Repository Pattern In ASP.NET Core

See Also

I would recommend one more article which describes set up and configuration for ASP.NET Core.

  1. Overview Of ASP.NET Core
  2. CRUD Operations in ASP.NET Core using Entity Framework Core Code First
  3. Repository Pattern In ASP.NET Core
  4. ASP.NET Core With Visual Studio 2017 RC

Conclusion

This article introduced CRUD operations in ASP.NET Core using Entity Framework Core with "code first" development approach. We used bootstrap CSS and JavaScript for the user interface design in this application. What do you think about this article? Please provide your feedback.