我需要NHibernate的帮助。我正在使用2.1,但也尝试了3,结果相同。任何帮助最受赞赏!
当使用NHibernate执行ICriteria查询时,它执行查询,然后对于查询中的每个结果,它执行另一个查询以选择关联对象,该对象已在初始结果集中返回,因为我正在使用预先加载。这当然导致了令人沮丧的表现。使用下面的映射文件,Nhibernate生成的查询完全符合以下预期:
exec sp_executesql N'SELECT top 20 this_.ContactCode as ContactC1_48_1_, this_.IsActive as IsActive48_1_, contact2_.ContactCode as ContactC1_47_0_, contact2_.ContactFullName as ContactF2_47_0_ FROM Clients this_ left outer join Contacts contact2_ on this_.ContactCode=contact2_.ContactCode WHERE this_.ContactCode like @p0 and this_.IsActive = @p1 ORDER BY this_.ContactCode asc',N'@p0 nvarchar(7),@p1 bit',@p0=N'DAL001%',@p1=1
此查询返回单个记录,然而会立即跟随以下查询,该查询检索相关联系人对象的详细信息,该联系人对象已在初始查询中完整返回,并且当然,当返回许多记录时,会执行N个附加查询。这完全出乎意料!
exec sp_executesql N'SELECT contact0_.ContactCode as ContactC1_47_0_, contact0_.ContactFullName as ContactF2_47_0_ FROM Contacts contact0_ WHERE contact0_.ContactCode=@p0',N'@p0 nvarchar(6)',@p0=N'DAL001'
延迟加载已关闭。 ICriteria代码如下:
ICriteria clientsFromContactCodeQuery = session.CreateCriteria<Client>()
.Add(Restrictions.Like("ContactCode", id + "%"))
.Add(Restrictions.Eq("IsActive", true))
.AddOrder(Order.Asc("ContactCode"))
.SetMaxResults(maxResultCount);
var clientsFromContactCodeList = clientsFromContactCodeQuery.List();
我有一个简单的nhibernate映射文件:
<class name="Contact" table="Contacts" lazy="false">
<id name="ContactCode">
<generator class="assigned" />
</id>
<property name="ContactFullName" />
</class>
<class name="Client" table="Clients" lazy="false">
<id name="ContactCode">
<generator class="assigned" />
</id>
<property name="IsActive" />
<one-to-one
name="Contact"
class="Contact"
lazy="false"
fetch="join"
/>
</class>
答案 0 :(得分:2)
启用延迟加载,然后使用HQL查询预取所需的子项。
from Client c
left join fetch c.Contact
where
c.ContactCode like :id
and
c.IsActive eq true
我不知道语法的顺序和HQL可能需要稍微调整,但这是解决方案的核心。
答案 1 :(得分:0)
如果还没有,请尝试将max_fetch_depth属性设置为2或3。不确定这是否与一对一的关系有效。
<property name="max_fetch_depth">3</property>
答案 2 :(得分:0)
最奇怪的是,在尝试对查询进行各种更改后,从hql到icriteria格式,没有任何效果。但是,我注意到一些数据没有生成N + 1个查询。事实证明,联系人和客户端表中的主键最后有SPACES,删除后修复了问题!
很奇怪,但感谢你的帮助。