6

我正在学习领域驱动设计。我目前正在尝试用 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) { ... }
}

当然,这会起作用,但我会失去域模型的简单性和优雅性。

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

4

2 回答 2

3

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

于 2011-08-29T07:55:44.257 回答
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

于 2011-08-28T21:08:05.593 回答