在哪里放置NHibernate查询逻辑?

时间:2010-05-11 13:44:00

标签: fluent-nhibernate domain-driven-design linq-to-nhibernate

我正在尝试使用Fluent NHibernate和Linq到NHibernate建立适当的域架构。我让我的控制器调用我的Repository类,它们在引擎盖下执行NHibernate并传回ICollections数据。这似乎很有效,因为它抽象了数据访问并将NHibernate功能保持在“精细打印”中。

但是,现在我发现我的控制器需要在不同的上下文中使用相同的数据调用。例如,我的repo返回一个Users列表。当我想显示用户列表时,这很好,但是当我想开始利用子类来显示角色等时,我遇到了SELECT N + 1问题。我知道如何在NHibernate中更改它,所以它使用连接,但我的具体问题是我在哪里放这个逻辑?我不希望每个GetAllUsers()调用也返回角色,但我确实想要其中的一些。

所以这是我看到的三个选项:

  1. 更改映射中的设置,以便将角色加入我的查询。
  2. 创建两个存储库调用 - GetAllUsers()和GetUsersAndRoles()。
  3. 将我的IQueryable对象从存储库返回到Controller并使用NHibernate Expand方法。
  4. 很抱歉,如果我没有解释清楚这一点。我刚刚进入DDD,很多这个术语对我来说还是新的。谢谢!

4 个答案:

答案 0 :(得分:2)

正如lomaxx指出的那样,你需要query.Expand。

为了防止您的存储库因各种可能情况的各种方法而变得模糊,您可以创建查询对象来进行可配置的查询。

我使用ICriteria API on my blog发布了一些示例。 ICriteria API有FetchMode而不是Expand,但想法是一样的。

答案 1 :(得分:1)

我尝试将所有查询逻辑保存在我的存储库中,并尝试仅从它们传回ICollection。

在你的情况下,我会传递一些参数来确定你是否想要加载角色,并以这种方式构建IQueryable。例如:

GetAllUsers(bool loadRoles)
{
    var query = session.Linq<Users>();
    if(loadRoles)
       query.Expand("Roles");
    return query.ToList();
}

答案 2 :(得分:0)

我会选择2,创建两个存储库。也许我会考虑为GetRoleByUser(用户用户)创建另一个存储库调用。因此,如果需要,您可以在单独的线程上更改用户选择时访问用户的角色,这样会增加您的性能,并且不会为每个用户加载每个用户的角色,这将需要大多数资源。

答案 3 :(得分:0)

听起来你问是否有可能使GetAllUsers()有时只返回用户实体,有时会返回用户和角色。

我要么创建一个名为GetRolesForUser(User user)的单独存储库方法,对Roles使用延迟加载,或者使用lomaxx答案中提到的GetAllUsers(bool loadRoles)

我会倾向于在您的存储库中使用延迟加载角色或单独的方法。