如何通过Ardalis Specification全局过滤实现ISoftDelete的实体软删除数据?
实现Ardalis Specification自动过滤软删除实体的方案
下面提供几种可行的单点实现方案,避免手动为每个Specification添加软删除过滤条件:
1. 自定义通用Specification基类
创建一个继承自Specification<T>的基类,在构造逻辑中自动为实现ISoftDelete的实体添加过滤规则,所有业务Specification都继承这个基类即可。
public class BaseSpecification<T> : Specification<T> where T : class { protected BaseSpecification() { ApplySoftDeleteFilter(); } protected BaseSpecification(Expression<Func<T, bool>> criteria) : base(criteria) { ApplySoftDeleteFilter(); } private void ApplySoftDeleteFilter() { if (typeof(ISoftDelete).IsAssignableFrom(typeof(T))) { Query.Where(entity => !((ISoftDelete)entity).IsDeleted); } } }
特殊场景处理
如果需要查询已删除的实体,可以创建一个派生类,移除或反转过滤条件:
public class IncludeDeletedSpecification<T> : BaseSpecification<T> where T : class, ISoftDelete { public IncludeDeletedSpecification() : base() { Query.ClearWhereClauses(); Query.Where(entity => entity.IsDeleted); } public IncludeDeletedSpecification(Expression<Func<T, bool>> criteria) : base(criteria) { Query.ClearWhereClauses(); Query.Where(criteria).Where(entity => entity.IsDeleted); } }
2. 全局重写SpecificationEvaluator
通过替换Ardalis默认的SpecificationEvaluator,在查询评估阶段自动注入软删除过滤规则,无需修改现有Specification基类。
步骤1:自定义Evaluator
public class SoftDeleteSpecificationEvaluator : SpecificationEvaluator { public override IQueryable<T> GetQuery<T>(IQueryable<T> inputQuery, ISpecification<T> specification) where T : class { var query = base.GetQuery(inputQuery, specification); // 仅对实现ISoftDelete且未标记"包含已删除"的实体应用过滤 if (typeof(ISoftDelete).IsAssignableFrom(typeof(T)) && !specification.GetType().GetInterfaces().Contains(typeof(IIncludeDeleted))) { query = query.Where(entity => !((ISoftDelete)entity).IsDeleted); } return query; } } // 标记接口:用于允许查询已删除数据 public interface IIncludeDeleted { }
步骤2:替换DI容器中的默认实现
在Startup/Program.cs中注册自定义Evaluator:
services.AddScoped<ISpecificationEvaluator, SoftDeleteSpecificationEvaluator>();
使用方式
常规查询自动过滤软删除数据;如果需要包含已删除实体,只需让对应的Specification实现IIncludeDeleted接口即可:
public class DeletedOrdersSpecification : Specification<Order>, IIncludeDeleted { // 业务查询逻辑... }
3. 扩展方法快速添加过滤规则
如果不想修改基类或全局Evaluator,可以写一个扩展方法,在Specification构造中快速添加过滤:
public static class SpecificationExtensions { public static ISpecificationBuilder<T> IgnoreSoftDeleted<T>(this ISpecificationBuilder<T> builder) where T : class { if (typeof(ISoftDelete).IsAssignableFrom(typeof(T))) { builder.Query.Where(entity => !((ISoftDelete)entity).IsDeleted); } return builder; } }
在Specification中使用:
public class ActiveProductsSpecification : Specification<Product> { public ActiveProductsSpecification() { Query.IgnoreSoftDeleted(); // 其他查询条件... } }
内容的提问来源于stack exchange,提问作者WorkInProgress
相关产品推荐
相关产品推荐

