我有一个类图,它与下面的类似。
我使用这个例子是因为它比解释我正在处理的域更简单
public class Cheque {
public FinanceAccount Account {get;set;}
public Customer customer {get;set;}
public Branch Branch {get;set;}
}
一个Cheque
实体和其余三个实体具有ManyToOne
关系。
目前的关系不是双向的。
如何编写一个有效的Futures Query来获取Cheques
的列表,这样我就不会得到加载Account
、Customer
、Branch
的N+1?
我尝试过使用左联接,但想知道是否可以使用简化的SQL 来实现这一点
我们可以实现所需的结果(没有N+1),但Futures不是正确的NHibernate功能。我们可以使用它们,但获取many-to-one
实体的技巧在其他地方(见下文)。此处所述的期货:http://ayende.com/blog/3979/nhibernate-futures平均值:
Future()和FutureValue()本质上是一种将查询执行推迟到以后的方式,此时NHibernate将有更多关于应用程序应该做什么的信息,并相应地进行优化
因此,我们可以将更多的查询放入一个批次中。例如,查询可以是一组查询,结果是:
- 支票总额
- 前20张支票投影
- 上周提取的最大金额
- 等等
因此,在这种情况下,我们可以将"不同"类型的查询放入Future
中。
但是要在没有N+1的情况下获取many-to-one
实体,我们可以使用标准的Criteria API。因此,即使这些属性被映射为懒惰的select作为fetch:
<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 select语句,连接Cheque及其引用属性。