Entity Framework Core怎么实现软删除 EF Core全局查询过滤器用法

发布时间 - 2025-12-30 00:00:00    点击率:
EF Core软删除通过全局查询过滤器自动添加IsDeleted==false条件并重写SaveChanges将Deleted状态改为Modified来实现。需定义ISoftDelete接口和BaseEntity基类,批量配置过滤器,慎用IgnoreQueryFilters()。

EF Core 实现软删除,核心是配合 全局查询过滤器(Global Query Filters) 自动对所有查询添加条件(如 IsDeleted == false),同时在删除操作中不真正删数据,而是标记为已删除。关键在于配置一致、避免绕过、注意导航属性和显式加载的兼容性。

定义软删除接口和实体基类

统一管理软删除字段,便于复用和约束:

  • 定义接口 ISoftDelete,含 IsDeleted 和可选的 DeletedAt 属性
  • 让需要软删除的实体继承一个基类(如 BaseEntity),实现该接口
  • 确保数据库字段对应(如 IsDeleted 类型为 bitboolean

示例:

public interface ISoftDelete
{
  bool IsDeleted { get; set; }
  DateTime? DeletedAt { get; set; }
}

public abstract class BaseEntity : ISoftDelete
{
  public bool IsDeleted { get; set; }
  public DateTime? DeletedAt { get; set; }
}

在 DbContext 中配置全局查询过滤器

OnModelCreating 中为每个支持软删除的实体启用过滤器:

  • 使用 modelBuilder.Entity().HasQueryFilter(x => !x.IsDeleted)
  • 推荐用泛型方式批量注册,避免漏配;可用反射扫描继承自 BaseEntity 的类型
  • 过滤器会在所有 LINQ 查询(包括 Include 导航属性)中自动生效

示例(手动配置):

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
  modelBuilder.Entity().HasQueryFilter(u => !u.IsDeleted);
  modelBuilder.Entity().HasQueryFilter(p => !p.IsDeleted);
}

重写 Delete 方法实现软删除逻辑

EF Core 默认调用 Remove() 会触发物理删除,需改为更新状态:

  • 重写 SaveChanges / SaveChangesAsync,扫描待删除实体,将其标记为 IsDeleted = true,并取消物理删除操作
  • 将实体状态从 Deleted 改为 Modified,仅更新软删除字段
  • 注意:需排除已真正删除(如系统日志等不需要软删)的实体类型

示例片段:

public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
  foreach (var entry in ChangeTracker.Entries())
  {
    if (entry.State == EntityState.Deleted)
    {
      entry.State = EntityState.Modified;
      entry.CurrentValues["IsDeleted"] = true;
      entry.CurrentValues["DeletedAt"] = DateTime.UtcNow;
    }
  }
  return base.SaveChanges(acceptAllChangesOnSuccess);
}

绕过过滤器的场景与安全处理

某些业务需要查“已删除”数据(如回收站),EF Core 提供 IgnoreQueryFilters()

  • 仅限可信上下文使用,例如后台管理页,避免暴露给前端随意调用
  • 注意:它会跳过所有过滤器(不止软删除),慎用于包含多过滤器的模型
  • 也可用 AsNoTrackingWithIdentityResolution() 配合,但不推荐替代过滤器绕过

示例:

var deletedUsers = context.Users
  .IgnoreQueryFilters()
  .Where(u => u.IsDeleted)
  .ToList();

基本上就这些。全局过滤器 + 状态拦截是 EF Core 软删除最稳妥的组合,既保持代码简洁,又避免业务层遗漏判断。注意测试导航查询、显式加载和批量操作是否符合预期。


# 前端  # Boolean  # if  # foreach  # include  # bool  # int  # void  # 继承  # 接口  # class  # public  # protected  # Interface  # 泛型  # var  # delete  # 数据库  # linq  # 重写  # 加载  # 不需要  # 会在  # 将其  # 可选  # 仅限  # 但不  # 它会  # 来实现 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Laravel怎么使用Intervention Image库处理图片上传和缩放  Android利用动画实现背景逐渐变暗  智能起名网站制作软件有哪些,制作logo的软件?  个人摄影网站制作流程,摄影爱好者都去什么网站?  详解Nginx + Tomcat 反向代理 如何在高效的在一台服务器部署多个站点  打开php文件提示内存不足_怎么调整php内存限制【解决方案】  微信公众帐号开发教程之图文消息全攻略  Laravel怎么生成URL_Laravel路由命名与URL生成函数详解  高防网站服务器:DDoS防御与BGP线路的AI智能防护方案  C语言设计一个闪闪的圣诞树  如何快速辨别茅台真假?关键步骤解析  Laravel软删除怎么实现_Laravel Eloquent SoftDeletes功能使用教程  Laravel如何自定义错误页面(404, 500)?(代码示例)  公司门户网站制作公司有哪些,怎样使用wordpress制作一个企业网站?  详解Oracle修改字段类型方法总结  如何彻底删除建站之星生成的Banner?  如何用腾讯建站主机快速创建免费网站?  网站制作大概要多少钱一个,做一个平台网站大概多少钱?  laravel怎么实现图片的压缩和裁剪_laravel图片压缩与裁剪方法  Laravel中Service Container是做什么的_Laravel服务容器与依赖注入核心概念解析  Laravel怎么创建自己的包(Package)_Laravel扩展包开发入门到发布  在线制作视频的网站有哪些,电脑如何制作视频短片?  香港网站服务器数量如何影响SEO优化效果?  Win11搜索栏无法输入_解决Win11开始菜单搜索没反应问题【技巧】  免费的流程图制作网站有哪些,2025年教师初级职称申报网上流程?  如何在万网自助建站平台快速创建网站?  原生JS获取元素集合的子元素宽度实例  如何有效防御Web建站篡改攻击?  香港服务器网站生成指南:免费资源整合与高速稳定配置方案  弹幕视频网站制作教程下载,弹幕视频网站是什么意思?  HTML透明颜色代码怎么让下拉菜单透明_下拉菜单透明背景指南【技巧】  Laravel如何设置定时任务(Cron Job)_Laravel调度器与任务计划配置  手机网站制作平台,手机靓号代理商怎么制作属于自己的手机靓号网站?  如何用AI帮你把自己的生活经历写成一个有趣的故事?  专业企业网站设计制作公司,如何理解商贸企业的统一配送和分销网络建设?  php结合redis实现高并发下的抢购、秒杀功能的实例  如何用低价快速搭建高质量网站?  HTML5建模怎么导出为FBX格式_FBX格式兼容性及导出步骤【指南】  Laravel Sail是什么_基于Docker的Laravel本地开发环境Sail入门  微信小程序 wx.uploadFile无法上传解决办法  如何生成腾讯云建站专用兑换码?  网站制作企业,网站的banner和导航栏是指什么?  Laravel如何处理JSON字段_Eloquent原生JSON字段类型操作教程  如何在宝塔面板中创建新站点?  活动邀请函制作网站有哪些,活动邀请函文案?  Laravel全局作用域是什么_Laravel Eloquent Global Scopes应用指南  如何在阿里云通过域名搭建网站?  javascript事件捕获机制【深入分析IE和DOM中的事件模型】  网站制作软件有哪些,制图软件有哪些?  如何用虚拟主机快速搭建网站?详细步骤解析