我有一个类图,类似于下面的图。
我正在使用此示例,因为它比解释我正在处理的域更简单。
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
?< / p>
我尝试过使用左连接,但想知道是否可以使用简化的SQL
来完成答案 0 :(得分:3)
我们可以达到所需的结果(没有N + 1) - 但Futures将不是正确的NHibernate功能。我们可以使用它们,但是获取many-to-one
实体的技巧在其他地方(见下文)。此处所述的期货:http://ayende.com/blog/3979/nhibernate-futures表示:
... Future()和FutureValue()本质上是一种将推迟查询执行的方式用于以后的日期,此时NHibernate将获得有关应用程序应该做什么的更多信息,并相应地优化它
因此我们可以将更多查询放入一个批处理中。查询可以是例如以下结果的查询集:
因此,在这种情况下,我们可以将“不同”类型的查询放入Future
。
但是要在没有N + 1的情况下获取many-to-one
个实体 - 我们可以使用标准Criteria API。因此,即使这些属性被映射为惰性,select也可以作为fetch:
<many-to-one name="Account" class="FinanceAccount" column="AccountId"
lazy="proxy" fetch="select"/>
此Criteria将只创建一个带左连接的选择:
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语句,加入Check及其引用属性。