【问题标题】:Where to put NHibernate query logic?NHibernate 查询逻辑放在哪里?
【发布时间】:2011-02-18 03:56:25
【问题描述】:

我正在尝试使用 Fluent NHibernate 和 Linq to NHibernate 设置适当的域架构。我有我的控制器调用我的存储库类,这些类在引擎盖下执行 NHibernate 并传回 ICollections 数据。这似乎运作良好,因为它抽象了数据访问并将 NHibernate 功能保持在“小字”中。

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

以下是我看到的三个选项:

  1. 更改我的映射中的设置,以便将角色加入到我的查询中。
  2. 创建两个存储库调用 - GetAllUsers() 和 GetUsersAndRoles()。
  3. 将我的 IQueryable 对象从存储库返回到控制器并使用 NHibernate Expand 方法。

对不起,如果我没有很好地解释这一点。我刚开始接触 DDD,很多这个术语对我来说仍然是新的。谢谢!

【问题讨论】:

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


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

      • 我喜欢这个答案,但我真的可以看到它在复杂的情况下变得疯狂。我的场景非常简单——我的真实情况有很多子对象。
      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

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

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

        【讨论】:

          猜你喜欢
          • 2014-03-16
          • 2011-09-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-03-15
          • 1970-01-01
          • 2012-01-22
          • 2011-06-03
          相关资源
          最近更新 更多