The Entity Framework Core executes UPDATE statement in the database for the entities whose EntityState is Modified. The DbContext’s Update() update method is used for performing the updation of records in the database.
Page Contents
We have Department and Employee entites:
public class Department
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Employee> Employee { get; set; }
}
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public string Designation { get; set; }
public int DepartmentId { get; set; }
public Department Department { get; set; } = null!;
}
Consider the below code where we are updating the Department name of the department with Id number 1. We are updating it’s name to Designing.
var dept = new Department()
{
Id = 1,
Name = "Designing"
};
context.Update(dept);
await context.SaveChangesAsync();
The EF Core is able to perform the update here is because we have given Id key value (which is ‘1’ in this case) for the department entity through which tracking of the entity is done.
If there is no valid key value then EF core will will consider it a new entity and perform the Insert operation on the database.
var dept = new Department()
{
Name = "Research"
};
context.Update(dept);
await context.SaveChangesAsync();
Here the .Update() method will insert a new Research record on the Department table.
The UpdateRange() method is used to Update Multiple Records at the same time. Consider the below code where we are updating 3 Department records at the same time.
var dept1 = new Department()
{
Id = 1,
Name = "New Designing"
};
var dept2 = new Department()
{
Id = 2,
Name = "New Research"
};
var dept3 = new Department()
{
Id = 3,
Name = "New HR"
};
List<Department> modifiedDept = new List<Department>() { dept1, dept2, dept3 };
context.UpdateRange(modifiedDept);
await context.SaveChangesAsync();
Entity Framework Core can also be used to Update Related Records. See the below code which updates the Employee and Department at the same time. The Department name is updated to ‘Admin_1’. This Department is the related record for the Employee Entity.
var dept = new Department()
{
Id = 5,
Name = "Admin_1"
};
var emp = new Employee()
{
Id = 1,
Name = "Matt_1",
Designation = "Head_1",
Department = dept
};
context.Update(emp);
await context.SaveChangesAsync();
When this code executes the employee id 1 gets his info changed to:
The related department also gets changed. This Employee Department name gets changed to “Admin_1”.
We will now perform the Update Records task in the CRUD OPERATIONS feature which we are building in the app. So first add the Update action methods on the DepartmentController.cs file. The code is shown below.
using EFCoreExample.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace EFCoreExample.Controllers
{
public class DepartmentController : Controller
{
private CompanyContext context;
public DepartmentController(CompanyContext cc)
{
context = cc;
}
public async Task<IActionResult> Update(int id)
{
Department dept = await context.Department.Where(e => e.Id == id).FirstOrDefaultAsync();
return View(dept);
}
[HttpPost]
public async Task<IActionResult> Update(Department dept)
{
context.Update(dept);
await context.SaveChangesAsync();
return RedirectToAction("Index");
}
//...
}
}
The 2 actions are added which are the HTTP GET and HTTP POST versions. In the GET Version we are getting the id of the department on the method’s parameter and then we are fetching the corresponding department record from the database. This record is returned to the update view where it will be shown to the user in a form.
The user will update the values for the department record and submit the form. The POST Version of the Update action will then be called and it receives the updated value of the department in it’s parameter through Model Binding technique. It then calls the Update() method and saves the record to the database by using the DbContext SaveChangesAsync() method.
Next add a new razor view file called Update.cshtml inside the Views/Department folder with the following code.
@{
ViewData["Title"] = "Update Department";
}
@model Department
<h1 class="bg-info text-white">Update Department</h1>
<a asp-action="Index" class="btn btn-secondary">Back</a>
<form method="post">
<div class="form-group">
<label asp-for="Name"></label>
<input asp-for="Name" class="form-control" />
</div>
<button type="submit" class="btn btn-primary">Update</button>
</form>
The below image shows the update department form.
We will also need to link the update feature from the Index view file. Recall that the Index.cshtml view shows all the department records in a table. We built this feature on the previous tutorial – Read Records in Entity Framework Core. So we update the Index view by adding an update column with a anchor link that will call the Update action on the Department controller by passing the department id on it’s route.
The added column is shown in highlighted color below.
@{
ViewData["Title"] = "All Departments";
}
@model IEnumerable<Department>
<h1 class="bg-info text-white">All Departments</h1>
<a asp-action="Create" class="btn btn-secondary">Create</a>
<table class="table table-sm table-bordered">
<tr>
<th>ID</th>
<th>Name</th>
<th>Update</th>
</tr>
@foreach (Department dept in Model)
{
<tr>
<td>@dept.Id</td>
<td>@dept.Name</td>
<td>
<a class="btn btn-sm btn-primary" asp-action="Update" asp-route-id="@dept.Id">
Update
</a>
</td>
</tr>
}
</table>
Run the app and visit the department controller link – https://localhost:7018/Department where the departments records are shown along with the update button. Click on an update button to update the corresponding department record. Check the below image.
Lets do the same with the EmployeeController.cs by adding Update action methods to it.
using EFCoreExample.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
namespace EFCoreExample.Controllers
{
public class EmployeeController : Controller
{
private CompanyContext context;
public EmployeeController(CompanyContext cc)
{
context = cc;
}
public async Task<IActionResult> Update(int id)
{
Employee emp = await context.Employee.Where(e => e.Id == id).FirstOrDefaultAsync();
List<SelectListItem> dept = new List<SelectListItem>();
dept = context.Department.Select(x => new SelectListItem { Text = x.Name, Value = x.Id.ToString() }).ToList();
ViewBag.Department = dept;
return View(emp);
}
[HttpPost]
public async Task<IActionResult> Update(Employee emp)
{
context.Update(emp);
await context.SaveChangesAsync();
return RedirectToAction("Index");
}
//...
}
}
Similar to the department controller’s update action, we are doing the same thing here by fetching the employee record from the database whose id is provided on the method’s parameter.
We are also fetching all the departments and adding them to List<SelectListItem> object and then to a ViewBag. The departments will be shown in html select control on the view.
List<SelectListItem> dept = new List<SelectListItem>();
dept = context.Department.Select(x => new SelectListItem { Text = x.Name, Value = x.Id.ToString() }).ToList();
ViewBag.Department = dept;
The update code with TryUpdateModelAsync is given below:
[HttpPost]
public async Task<IActionResult> Update(int? id)
{
if (id == null)
{
return NotFound();
}
var employeeToUpdate = await context.Employee.FirstOrDefaultAsync(s => s.Id == id);
if (await TryUpdateModelAsync<Employee>(
employeeToUpdate,
"",
s => s.Name, s => s.DepartmentId, s => s.Designation))
{
try
{
await context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
catch (DbUpdateException /* ex */)
{
//Log the error (uncomment ex variable name and write a log.)
ModelState.AddModelError("", "Unable to save changes. " +
"Try again, and if the problem persists, " +
"see your system administrator.");
}
}
return View(employeeToUpdate);
}
Here we have int type parameter for the employee id. We then are reading the employee entity with the given id from the database and then calling TryUpdateModel, passing in an explicit allowed properties list that needs to be updated. These are Name, DepartmentId and Designation.
Next, add the Update.cshtml razor view file inside the Views/Employee folder with the following it. The view will show the employee record on a form for the user to update it’s fields.
@{
ViewData["Title"] = "Update Employee";
}
@model Employee
<h1 class="bg-info text-white">Create Employee</h1>
<a asp-action="Index" class="btn btn-secondary">Back</a>
<form method="post">
<div class="form-group">
<label asp-for="Name"></label>
<input asp-for="Name" class="form-control" />
</div>
<div class="form-group">
<label asp-for="Department"></label>
<select asp-for="DepartmentId" asp-items="ViewBag.Department" class="form-control"></select>
</div>
<div class="form-group">
<label asp-for="Designation"></label>
<input asp-for="Designation" class="form-control" />
</div>
<button type="submit" class="btn btn-primary">Create</button>
</form>
The update employee form will look as shown by the below image.
The final thing to do is to add the Update links to the Index view of the Employee controller. The code to add is shown in highlighted manner below.
@{
ViewData["Title"] = "All Employees";
}
@model IEnumerable<Employee>
<h1 class="bg-info text-white">All Employees</h1>
<a asp-action="Create" class="btn btn-secondary">Create</a>
<table class="table table-sm table-bordered">
<tr>
<th>ID</th>
<th>Name</th>
<th>Designation</th>
<th>Department</th>
<th>Update</th>
</tr>
@foreach (Employee emp in Model)
{
<tr>
<td>@emp.Id</td>
<td>@emp.Name</td>
<td>@emp.Designation</td>
<td>@emp.Department.Name</td>
<td>
<a class="btn btn-sm btn-primary" asp-action="Update" asp-route-id="@emp.Id">
Update
</a>
</td>
</tr>
}
</table>
Run the app and visit the employee controller link – https://localhost:7018/Employee. Here see the update links against all the employees, click any one and update the employee.
Download the source codes:
In this Entity Framework Core Update Records tutorial we covered how to uddate a record, multiple records and related recods. We also created Update Records CRUD Operations feature at the end. Next tutorial will be on Delete Records in Entity Framework Core.