我正在尝试执行一个简单的queryover,这很好用,但是使用nhibernate profiler我发现它执行的查询多于应有的次数。
我的实体:
轮廓:
public class Profile {
public int id {get;set;}
public List<GufBeProfile> Gufim {get;set;}
}
public class GufBeProfile {
public int Id {get;set;}
public Guf Guf {get;set;}
public Profile Profile {get;set;}
public List<HarshaaBeModule> Harshaaot {get;set;}
}
public class HarshhaBeModule {
public int id{get;set;}
public Harshaa Harshaa {get;set;}
public Module Module {get;set;}
}
这是我的查询:
GufBeProfile gufAlias = null;
HarshaaBeModule moduleAlias = null;
session.QueryOver<Profile>()
.JoinAlias(x => x.Gufim, () => gufAlias)
.JoinAlias(() => gufAlias.Harshaaot, () => moduleAlias)
.SingleOrDefault();
执行完查询后,分析器显示此查询:
-从两个连接的配置文件表中获取。
使用AutoMapper将结果转换为DTO对象后,分析器将显示另外2个查询:
-从GufBeProfile表中获取。
-从HarshaaBeModule表中获取。
我以为joinAlias应该阻止它。
这里发生了什么?
最佳答案
您尚未发布配置代码。您要加载lazy
吗?
如果您使用的是xml映射,是否正在执行以下操作?
<class name="A" table="A" lazy="true">
如果是这样,这就是NHibernate生成多个查询的原因。
NHibernate首先生成查询以从主表获取所有行,而没有任何从属表的数据。然后,它为依赖表上的主键生成带有WHERE子句的新查询。然后,它将来自多个查询的输出与您的POCO或实体进行映射。
如果要避免这种情况,并要求NHibernate一次性检索数据,请尝试使用预先加载。对于.hbm文件,您可以通过设置
lazy="false"
来实现。另外(或者)对关联设置获取机制,如下所示:-
<set name="PocoName" table="TableName" fetch="join">
更新1:
我同意@DavidOsborne在他的评论中所说的。
以下是他提到的link的副本:-
相反,我们保留默认行为,并将其覆盖
使用
left join fetch
中的HQL
进行特定交易。这说明NHibernate在第一个选择中使用以下命令急切地获取关联
外部联接。在
ICriteria
查询API中,您将使用SetFetchMode(FetchMode.Join)
。如果您希望自己可以更改获取策略
由
Get()
或Load()
使用,只需使用ICriteria
查询例:
User user = (User) session.CreateCriteria<User>()
.SetFetchMode("Permissions", FetchMode.Join)
.Add( Expression.Eq("Id", userId) )
.UniqueResult();
避免N + 1选择出现问题的一种完全不同的方法是
使用二级缓存。
关于c# - Nhibernate-尽管加入了QueryOver仍获取实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40450343/