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

基于DDD与Ardalis Clean架构,如何查询DocumentType列表?

解决方案

1. 在Document聚合根的仓储中新增查询方法

既然DocumentType属于Document聚合,直接在IDocumentRepository里加一个专门返回可用类型列表的方法,完全符合“仅为聚合根建仓储”的规则:

public interface IDocumentRepository : IRepository<Document>
{
    Task<IEnumerable<DocumentType>> GetAllDocumentTypesAsync(CancellationToken cancellationToken = default);
}

实现时可以直接查询数据库中所有不重复的DocumentType,如果是预定义类型也可以直接返回固定集合,灵活度很高。

2. 将DocumentType设计为值对象+静态/配置化列表

如果DocumentType是固定的业务分类(比如合同、发票、报告),把它做成值对象,同时在领域层维护一个可用类型的静态列表:

public record DocumentType(string Value)
{
    // 预定义类型
    public static readonly DocumentType Contract = new("Contract");
    public static readonly DocumentType Invoice = new("Invoice");
    public static readonly DocumentType Report = new("Report");

    // 返回所有可用类型
    public static IEnumerable<DocumentType> GetAll() => new[] { Contract, Invoice, Report };
}

前端直接调用DocumentType.GetAll()就能拿到列表,连数据库查询都省了。如果类型需要动态配置(比如从数据库加载),可以在领域层加个DocumentTypeProvider服务,依赖IDocumentRepository来获取数据。

3. 用领域服务封装类型查询逻辑

如果想保持仓储的单一职责,不想在仓储里加额外查询,可以创建一个DocumentTypeService领域服务,注入IDocumentRepository后封装查询逻辑:

public class DocumentTypeService
{
    private readonly IDocumentRepository _documentRepository;

    public DocumentTypeService(IDocumentRepository documentRepository)
    {
        _documentRepository = documentRepository;
    }

    public async Task<IEnumerable<DocumentType>> GetAvailableTypesAsync(CancellationToken cancellationToken)
    {
        var allDocuments = await _documentRepository.ListAsync(cancellationToken);
        return allDocuments.Select(d => d.Type).Distinct();
    }
}

为什么不把DocumentType设为聚合根?

你的顾虑完全正确——DocumentType没有脱离Document的独立业务行为,单独做成聚合根会形成贫血模型,还会引入不必要的复杂度,违背DDD“聚合根封装完整业务边界”的核心原则。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 21:06:07