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

问题描述 投票:0回答:2

我正在学习领域驱动设计。我目前正在尝试用 C# 编写一个简单的应用程序,使用 DDD 进行设计。该应用程序有一个聚合根 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) { ... }
}

这当然可行,但我会失去领域模型的简单性和优雅性。

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

c# pagination repository domain-driven-design aggregateroot
2个回答
3
投票

简短的回答是你不应该这样做。存储库的目的是使域对象的访问变得明确。它们不应用于出于 UI 目的对数据进行分页。这是完全不同的角色,我称之为Finder。为什么?您不想用分页等 UI 概念污染您的域(存储库属于域)。您可以在我的博客此处找到更详细的解释。


1
投票

如果您使用像 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

© www.soinside.com 2019 - 2024. All rights reserved.