我正在学习域驱动设计。我目前正在尝试使用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) { ... }
}
这肯定会起作用,但我会放弃领域模型的简洁和优雅。
如何使用存储库模式处理子实体的分页的最佳实践是什么?我不是在寻找如何使用特定的库等来处理这个问题,而是在“模式级别”上处理它。
答案 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