假设我有一个域模型,其中有一个名为 Blog 的类,该类有一个名为 BlogEntries 的属性(包含 BlogEntry 类型的对象)。如果我有一个包含两个表“Blog”和“BlogEntry”的数据库模型,那么我的博客有 1000 个博客条目也不是不可能的。如果我要在网站上显示博客,我只想一次显示大约 20 个博客条目,因此我必须使用某种分页。我显然不希望一直从数据库中获取 1000 条记录。
我该如何去做呢? BlogEntries 属性是否应该位于 Blog 域对象中,或者可能位于存储库中?我仍然希望能够添加博客条目以及获取现有博客条目的分页结果。 NHibernate 映射会是什么样子?
博客/博客条目只是一个示例,它也可以是客户/订单示例或任何其他主/详细场景。
我会让 BlogEntry 成为自己的聚合根,并拥有自己的存储库。您可以通过查询具有给定 BlogID 的所有 BlogEntry 的 BlogEntry 存储库来获取特定 Blog 的 BlogEntry 实例。除此之外,我无法提供有关存储库的详细信息,因为实现存储库有几种不同的策略(一个通用存储库与多个存储库、单独的查找方法与采用复杂规范对象的查找方法等)。存储库的 finder 方法应该支持分页。
public class Blog
{
public int ID {get;set;}
// other stuff
}
public class BlogEntry
{
public int ID {get;set;}
public int BlogID {get;set;}
}
public class BlogEntryRepository
{
public IEnumerable<BlogEntry> FindByBlogID(
int blogID, int pageIndex, int pageSize)
{
// implementation
}
}
或者,(同样将 BlogEntry 建模为聚合根)您可以将 BlogEntryID 的集合添加到您的 Blog 类中。这比将 BlogEntry 实例本身放在 Blog 类中更好,因为当您想要获取 Blog 实例时,需要加载的数据要少得多。使用这些 ID,您可以选择其中的子集并将它们传递到接受 ID 集合的 BlogEntry 存储库方法。换句话说,您的域中会有更多的逻辑来支持分页,并且存储库中会有更通用的 getter。
public class Blog
{
public int ID {get;set;}
public IEnumerable<int> BlogEntryIDs {get;set;}
// other stuff
}
public class BlogEntry
{
public int ID {get;set;}
public int BlogID {get;set;}
}
public class BlogEntryRepository
{
public IEnumerable<BlogEntry> Get(IEnumerable<int> blogEntryIDs)
{
// implementation
}
}
这种方法的用法如下
// get the second page
var entries =
blogEntryRepo.Get(blog.BlogEntryIDs).Skip(1 * PAGE_SIZE).Take(PAGE_SIZE);
在数据库中,您将返回多行,每个博客条目对应一行。 (我还喜欢返回多个结果集,以便在一次数据库往返中从所有相关表中获取所有行。我还利用 SQL 2005 的 ROW_VERSION 函数来启用数据库分页。)
我通常更喜欢第二种方法,除非典型用法显示与博客关联的 BlogEntry 实例的数量令人望而却步(例如超过几千个)。太多 int 的数组会让我对性能和内存保持警惕。
您必须访问它自己的存储库中的 blogentry 才能获取分页列表。
对于博客条目的集合,您可以使用 BatchSize 属性。它将使您不必从数据库中选择所有集合,而仅选择所需的值。