3

我有一个类似于下面的类图。

我正在使用这个示例,因为它比解释我正在处理的域更简单。

public class Cheque {

   public FinanceAccount Account {get;set;}

   public Customer customer {get;set;}

   public Branch Branch {get;set;}
}

一个Cheque实体ManyToOne与三个实体的其余部分有关系。

现在的关系不是双向的

如何编写一个有效的期货查询来获取一个列表,Cheques这样我就不会得到 N+1 来加载Account, Customer, Branch

我尝试过使用左连接,但想知道这是否可以使用简化的 SQL 来完成

4

1 回答 1

3

我们可以达到所需的结果(没有 N+1)——但 Futures 不会是正确的 NHibernate 功能。我们可以使用它们,但获取many-to-one实体的技巧在别处(见下文)。此处所述的期货:http ://ayende.com/blog/3979/nhibernate-futures 的意思是:

... Future() 和 FutureValue() 本质上是一种将查询执行推迟到以后执行的方式,此时 NHibernate 将获得有关应用程序应该做什么的更多信息,并相应地对其进行优化

所以我们可以把更多的查询放到一个批次中。查询可以是例如一组查询,结果是:

  • 总检查
  • 前 20 个检查预测
  • 上周提取的最大金额
  • 等等

因此,在这种情况下,我们可以将“不同”类型的查询放入Future.

但是要获取many-to-one没有 N+1 的实体 - 我们可以使用标准 Criteria API。因此,即使这些属性被映射为懒惰的选择作为获取:

<many-to-one name="Account" class="FinanceAccount" column="AccountId" 
       lazy="proxy" fetch="select"/>

此标准将仅创建一个带有左连接的选择:

var list = session.CreateCriteria<Cheque>()
  .SetFetchMode("Account", NHibernate.FetchMode.Join)
  .SetFetchMode("customer", NHibernate.FetchMode.Join)
  .SetFetchMode("Branch", NHibernate.FetchMode.Join)
  .Future<Cheque>()
  // or
  // .List<Cheque>() ... will be the same right now
  ;

这将导致只有一个 SQL 选择语句,加入 Check 及其引用属性。

于 2012-12-01T17:32:34.967 回答