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