EF Core如何实现软删除 EF Core软删除查询过滤器方法

来源:这里教程网 时间:2026-02-21 17:36:45 作者:

EF Core 实现软删除,核心是用 查询过滤器(Query Filter) 自动屏蔽已标记为“删除”的数据,而不是真正从数据库删掉。它不依赖手写

.Where(!x.IsDeleted)
,而是让每次查询都透明生效——既安全又省心。

加一个 IsDeleted 字段

在要支持软删除的实体类里,添加布尔类型的标记属性:

推荐命名为
IsDeleted
,类型为
bool
,默认值设为
false
如果需要记录删除时间或操作人,可额外加
DeletedAt
DeletedBy
字段
不要对一对一关联实体单独软删除,容易引发导航属性异常

在 DbContext 中配置查询过滤器

重写

OnModelCreating
方法,为实体启用全局过滤:

基础写法:
modelBuilder.Entity<post>().HasQueryFilter(p => !p.IsDeleted);</post>
字段存为整数(如数据库用
TINYINT
)?加上值转换:
.Property(e => e.IsDeleted).HasConversion<int>()</int>
多个实体统一处理?可用反射遍历实现
IDeletable
接口的类型,自动注册过滤器

覆盖删除行为:把 Delete 变成 Update

调用

Remove()
时,EF 默认会生成 DELETE SQL。要改成软删除,得拦截保存前的操作:

重写
SaveChanges
SaveChangesAsync
遍历
ChangeTracker.Entries()
,对
EntityState.Deleted
的条目改为
Modified
,并把
IsDeleted
设为
true
新增数据时确保
IsDeleted
默认为
false
(可在
Added
分支中设置)

需要查已删除数据?临时绕过过滤器

管理后台或恢复功能常需看到全部记录,这时可以用:

context.Posts.IgnoreQueryFilters().Where(p => p.IsDeleted).ToList()
注意:
IgnoreQueryFilters()
会跳过该实体上所有过滤器,不只是软删除那个
如需更灵活控制(比如只在某些场景下包含已删数据),建议构造不同 DbContext 实例,或通过构造函数传入开关参数

基本上就这些。不复杂但容易忽略细节,比如没改 SaveChanges 行为会导致物理删除,或者忘了给关联实体配过滤器导致数据不一致。

相关推荐