如何使用存储库模式处理子实体的分页?

时间:2011-08-28 18:42:06

标签: c# domain-driven-design repository paging aggregateroot

我正在学习域驱动设计。我目前正在尝试使用DDD在C#中编写一个简单的应用程序。此应用程序有一个聚合根A,它可以包含0..n子实体B.这可以用以下内容表示:

class A {
    public int Id { get; }
    public IList<B> { get; }
}

有一个存储库:

class ARepository {
    public A Get(int id) { ... }
    public void SaveOrUpdate(A root) { ... }
    public void Delete(A root) { ... }
}

但是,我想在为给定的A实例呈现B子实体时添加分页。我该怎么做呢?我能想到的最好的方法是将A和ARepository改为:

class A {
    public int Id { get; }
}

class ARepository {
    public A Get(int id) { ... }
    public void SaveOrUpdate(A root) { ... }
    public void Delete(A root) { ... }

    public IList<B> GetBForA(A root, int offset, int pageSize, out int numPages) { ... }
}

这肯定会起作用,但我会放弃领域模型的简洁和优雅。

如何使用存储库模式处理子实体的分页的最佳实践是什么?我不是在寻找如何使用特定的库等来处理这个问题,而是在“模式级别”上处理它。

2 个答案:

答案 0 :(得分:3)

简短的回答是你不应该这样做。存储库的目的是使访问域对象显式化。它们不应用于为用户界面分页数据。这是完全不同的角色,我称之为 Finder 。为什么?您不希望使用分页等UI概念污染您的域(存储库属于域)。您可以在我的博客上找到更详细的解释here

答案 1 :(得分:0)

如果你正在使用像NHibernate这样的ORM,你可以通过设置延迟加载的集合属性(IList)来实现这一点,并急切地获取对象本身而不是存储库所需的页面或标准。例如:

var a = ARepository.Get(1);
var secondPageOfBs = a.BList.AsQueryable()
                                          .OrderBy(c => c.Name)
                                          .Skip(PageSize * 2)
                                          .Take(PageSize)
                                          .ToList();

您还可以在存储库中构建这些查询,并在域对象中获取结果,如:

var a = ARepository.GetWithPagedChildren(1, PageSize * 2, PageSize);

您还可以构建更复杂的急切查询,如下所述: http://ayende.com/blog/4367/eagerly-loading-entity-associations-efficiently-with-nhibernate