EF Core 的 Remove 方法标记实体为待删除,实际删除在 SaveChanges 时执行;支持断开模式(仅主键)和追踪模式(先查询后删),批量删用 RemoveRange,大表应避免;级联行为由 OnDelete 配置。
EF Core 的 Remove 方法用于标记一个实体为“待删除”,真正执行删除操作要等到调用 SaveChanges() 或 SaveChangesAsync() 时才发生。它不是直接发 SQL 删除语句,而是走变更追踪流程——所以用法和注意事项比看起来更关键。
适用于你**只知道 ID、没从数据库查过该实体**的场景。比如前端传了个 ID 要删,你不想先查再删(避免两次数据库往返):
context.Remove()
SaveChanges() 会抛出 DbUpdateConcurrencyException,提示“预期影响 1 行,实际影响 0 行”var student = new Student { StudentId = 100 };
context.Remove(student);
await context.SaveChangesAsync();
这是最安全、最推荐的方式:先用 Find()、FirstOrDefault() 等方法从数据库加载实体,再删:
Unchanged 状态,Remove() 会将其状态改为 Deleted
SaveChanges() 仍会报并发异常,但你能明确知道是“查到了但已被删”,而不是“根本不存在”var dept = await context.Departments.FindAsync(5);
if (dept != null)
{
context.Remove(dept);
await context.SaveChangesAsync();
}
用 RemoveRange() 一次删多个,支持传入集合或多个参数:
List、数组,甚至两个实体(如 RemoveRange(e1, e2))TRUNCATE 或 DELETE FROM
var toDelete = context.Students.Where(s => s.Status == "Inactive").ToList();
context.RemoveRange(toDelete);
await context.SaveChangesAsync();
如果实体有关联子项(如 Department 有多个 Employee),删父实体时子项是否自动删,取决于你在 OnModelCreating 中配置的 OnDelete() 行为:
DeleteBehavior.Cascade:删 Department 同时删所有关联 EmployeeDeleteBehavior.SetNull:Employee.DepartmentId 设为 NULL(要求字段可空)DeleteBehavior.Restric
t:禁止删,除非先清空子项dotnet ef migrations add 和 update
基本上就这些。核心就两点:删之前尽量确认实体存在,大表别用 RemoveRange 硬扛。