NHibernate 中的分页

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

假设我有一个域模型,其中有一个名为 Blog 的类,该类有一个名为 BlogEntries 的属性(包含 BlogEntry 类型的对象)。如果我有一个包含两个表“Blog”和“BlogEntry”的数据库模型,那么我的博客有 1000 个博客条目也不是不可能的。如果我要在网站上显示博客,我只想一次显示大约 20 个博客条目,因此我必须使用某种分页。我显然不希望一直从数据库中获取 1000 条记录。

我该如何去做呢? BlogEntries 属性是否应该位于 Blog 域对象中,或者可能位于存储库中?我仍然希望能够添加博客条目以及获取现有博客条目的分页结果。 NHibernate 映射会是什么样子?

博客/博客条目只是一个示例,它也可以是客户/订单示例或任何其他主/详细场景。

pagination nhibernate domain-driven-design
3个回答
1
投票

我会让 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 的数组会让我对性能和内存保持警惕。


1
投票

您必须访问它自己的存储库中的 blogentry 才能获取分页列表。


-1
投票

对于博客条目的集合,您可以使用 BatchSize 属性。它将使您不必从数据库中选择所有集合,而仅选择所需的值。

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