You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 19:23:14