Nhibernate N + 1查询问题

时间:2009-10-29 22:40:35

标签: nhibernate

我需要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>

3 个答案:

答案 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,删除后修复了问题!

很奇怪,但感谢你的帮助。