EF Core Remove方法怎么用 EF Core删除实体教程

EF Core 的 Remove 方法标记实体为待删除,实际删除在 SaveChanges 时执行;支持断开模式(仅主键)和追踪模式(先查询后删),批量删用 RemoveRange,大表应避免;级联行为由 OnDelete 配置。

EF Core 的 Remove 方法用于标记一个实体为“待删除”,真正执行删除操作要等到调用 SaveChanges()SaveChangesAsync() 时才发生。它不是直接发 SQL 删除语句,而是走变更追踪流程——所以用法和注意事项比看起来更关键。

删除单个已知主键的实体(断开模式)

适用于你**只知道 ID、没从数据库查过该实体**的场景。比如前端传了个 ID 要删,你不想先查再删(避免两次数据库往返):

  • 手动构造一个只带主键值的实体实例,传给 context.Remove()
  • EF Core 会尝试按主键去数据库删对应行;如果该主键在表中不存在,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)
  • 同样遵循“断开删需确保主键存在,追踪删更安全”的原则
  • 注意:它仍是逐条生成 DELETE 语句,**不适合清空大表**;大数据量建议用原生 SQL TRUNCATEDELETE FROM
  • 示例:
    var toDelete = context.Students.Where(s => s.Status == "Inactive").ToList();
    context.RemoveRange(toDelete);
    await context.SaveChangesAsync();

级联删除与外键行为

如果实体有关联子项(如 Department 有多个 Employee),删父实体时子项是否自动删,取决于你在 OnModelCreating 中配置的 OnDelete() 行为:

  • DeleteBehavior.Cascade:删 Department 同时删所有关联 Employee
  • DeleteBehavior.SetNull:Employee.DepartmentId 设为 NULL(要求字段可空)
  • DeleteBehavior.Restrict:禁止删,除非先清空子项
  • 配置后必须重新运行 dotnet ef migrations addupdate

基本上就这些。核心就两点:删之前尽量确认实体存在,大表别用 RemoveRange 硬扛。