Learn how to delete records from the database using Entity Framework Core. Deleting an entity is done using the Remove or RemoveRange method of the DbSet. Alternatively, you can also set the entity state as Deleted. We can delete records either in connected or disconnected Scenarios. We will also look at how to remove multiple records from the database using the RemoveRange method.
Source Code:
The source code of this project available in GitHub. It also contains the script of the database
Table of Contents
Delete Record
How you delete the entity depends on whether you are deleting the record in Connected or Disconnected scenario. In Connected Scenario, you can use the Remove or RemoveRange method to mark the record as Deleted. In Disconnected Scenario, you can attach it to the context and set its state as Deleted. Calling SaveChanges will send the delete query to the database.
Connected Scenario
Deleting in a connected scenario is very straight forward. Query the Department entity from the database. Call Remove method and pass the Department object to delete. The Change tracking in Entity Framework marks the entity as Deleted. Finally, SaveChanges will remove the Department from the database using the Delete Query
public void DeleteConnected()
{
Department department;
//Connected Scenario
using (EFCoreContext db = new EFCoreContext())
{
department = db.Departments.Where(d => d.Name == "Sales").First();
db.Departments.Remove(department);
db.SaveChanges();
}
}SQL Query
DELETE FROM [Departments]
WHERE [DepartmentID] = @p0;Disconnected Scenario
The following is the disconnected scenario example. First, we retrieve the Department entity and close the context. Later we open a new context and use the db.Entry method to set its state as Deleted. If the model is not in the context, then the Entry method adds it to the context and sets its state as Deleted
public void DeleteDisconnected()
{
Department department;
//Disconnected Scenario
using (EFCoreContext db = new EFCoreContext())
{
department = db.Departments.Where(d => d.Name == "Sales").First();
}
using (EFCoreContext db = new EFCoreContext())
{
//This also works
//db.Departments.Attach(department);
//db.Entry(department).State = System.Data.Entity.EntityState.Deleted;
db.Entry(department).State = EntityState.Deleted;
db.SaveChanges();
}
}Attach Method
You can also use the Attach and remove method as shown below. Note that Attach will add the entity to the context in Unchanged state.
db.Departments.Attach(dep);
db.Entry(dep).State = System.Data.Entity.EntityState.Deleted;Delete without loading from the database
You can delete the entity without loading from the database, provided you know the Primary key value. The following example shows how to delete without loading from the database. We create a new department entity and assign the 2 to DepartmentID. Next, we attach it to the context and set its state as Deleted. On SaveChanges the EF will delete the Department
public void DeleteDisconnectedWithoutLoading()
{
Department department;
department = new Department() { DepartmentID = 2 };
using (EFCoreContext db = new EFCoreContext())
{
db.Entry(department).State = EntityState.Deleted;
db.SaveChanges();
}
Console.WriteLine("Department {0} is Deleted ", department.DepartmentID);
Console.ReadKey();
}Delete & ConcurrencyCheck
The above code will not work if you have enabled ConcurrencyCheck on the table. For example, open the Department model and add the ConcurrencyCheck on the Name property as shown below.
public class Department
{
public int DepartmentID { get; set; }
[ConcurrencyCheck]
public string Name { get; set; }
public string Descr { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}Run the above code again and you will see the following exepction
Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: 'Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded
Delete Multiple Records
You can use RemoveRange method of DbSet to remove multiple records at a time. The following example code deletes 3 departments from the database in the connected scenario.
The EF sends one delete query at time to the database. So if you delete 100 records, the EF will issue 100 delete statements
public void DeleteMultipleRecordsConnected()
{
//Deleting Multiple Records
using (EFCoreContext db = new EFCoreContext())
{
List<Department> deps = db.Departments.Take(2).ToList();
db.Departments.RemoveRange(deps);
db.SaveChanges();
}
}The following code deletes the multiple records in disconnected scenario.
public void DeleteMultipleRecordsDisconnected()
{
List<Department> departments = new List<Department>();
departments.Add(new Department { DepartmentID = 1 });
departments.Add(new Department { DepartmentID = 2 });
//Deleting Multiple Records
using (EFCoreContext db = new EFCoreContext())
{
db.Entry(departments).State = EntityState.Deleted;
db.SaveChanges();
}
Console.ReadKey();
}
I have created a library to batch delete or update records with a round trip on EF Core 5.
Sample code as follows:
await ctx.DeleteRangeAsync(b => b.Price > n || b.AuthorName == “zack yang”);
await ctx.BatchUpdate()
.Set(b => b.Price, b => b.Price + 3)
.Set(b=>b.AuthorName,b=>b.Title.Substring(3,2)+b.AuthorName.ToUpper())
.Set(b => b.PubTime, b => DateTime.Now)
.Where(b => b.Id > n || b.AuthorName.StartsWith(“Zack”))
.ExecuteAsync();
Github repository: https://github.com/yangzhongke/Zack.EFCore.Batch
In “Delete without loading from the database with concurrency check” it is worth mentioning that if the concurrency value is passed while creating the object, it will not give the Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException exception