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

Ardalis.Specification库如何组合多个Specification实现可组合查询

Ardalis.Specification 多规则组合实现方案

Ardalis.Specification 原生支持多个Specification的组合拼接,完全可以满足复杂动态查询场景下拆分规则、避免大量条件判断的需求,和整洁架构的仓储模式适配度很高。

核心组合方法

你不需要修改已有的三个独立Specification代码,直接通过Query.AddSpecification()方法就能把多个规则叠加,所有通过该方法添加的Where条件默认会以AND逻辑拼接,正好匹配你需要的「同时满足资料完成、指定国家、创建时间晚于指定日期」的查询需求。
对应组合后的Specification实现如下:

public class ContactTargetQuerySpec : Specification<Contact>
{
    public ContactTargetQuerySpec(string countryCode, DateTime compareDate, bool isComplete = true)
    {
        Query
            // 叠加完成状态筛选规则
            .AddSpecification(new ContactByCompletion(isComplete))
            // 叠加创建时间筛选规则
            .AddSpecification(new ContactByCreationDateSuperiorThan(compareDate))
            // 叠加国家归属筛选规则
            .AddSpecification(new ContactByCountry(countryCode));
    }
}

这个组合后的Specification和普通单规则Specification用法完全一致,直接传入仓储的查询方法即可执行。

适配你的业务场景的实践方式

  • 动态增减筛选条件:你可以把每个筛选维度都拆成独立的细粒度Specification,在构造组合Specification时根据入参判断是否追加对应规则,完全替代零散写在Where里的条件判断。示例代码如下:
public class ContactDynamicFilterSpec : Specification<Contact>
{
    public ContactDynamicFilterSpec(ContactQueryRequest request)
    {
        // 仅当传入完成状态参数时追加对应筛选
        if (request.IsComplete.HasValue)
        {
            Query.AddSpecification(new ContactByCompletion(request.IsComplete.Value));
        }
        // 仅当传入起始时间参数时追加时间范围筛选
        if (request.CreateTimeStart.HasValue)
        {
            Query.AddSpecification(new ContactByCreationDateSuperiorThan(request.CreateTimeStart.Value));
        }
        // 仅当传入国家编码时追加归属地筛选
        if (!string.IsNullOrEmpty(request.CountryCode))
        {
            Query.AddSpecification(new ContactByCountry(request.CountryCode));
        }
    }
}
  • 按需加载关联实体:把关联实体加载(Include/ThenInclude)逻辑也拆成独立的Specification,比如写专门的ContactWithOrdersSpec、ContactWithTagsSpec,需要加载对应关联数据时就追加对应Specification即可。关联实体内部的筛选条件,可以直接写在对应Include的子查询里,组合时会自动合并生效。
  • 时间范围大小比较:你示例里的DateTime大于/小于筛选逻辑写在独立Specification里即可,组合时不会有任何冲突,支持任意数值、时间类型的比较规则拼接。

注意事项

  • 排序逻辑会被后添加的Specification覆盖:如果多个子Specification都配置了OrderBy/OrderByDescending规则,最终生效的是最后一个添加的排序。建议把排序逻辑和筛选逻辑拆分,做成独立的排序类Specification,按需追加,避免规则耦合。
  • 分页、忽略全局过滤器这类影响整个查询的配置,不要写在细粒度的子Specification里,统一放在最外层的组合Specification中配置,避免规则互相覆盖。
  • 如果需要实现OR逻辑的组合(即满足A规则或满足B规则),不要直接用AddSpecification,用库内置的OrSpecification<T>包装两个待组合的规则再添加即可,示例:Query.AddSpecification(new OrSpecification<Contact>(specA, specB))。

内容的提问来源于stack exchange,提问作者Arkena

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 20:18:25