我有一个表Parent和一个表Child.Child包含Parent表的外键,创建一对多关系.这是我使用流畅的NHibernate定义的映射的一部分:
public class ParentMap : ClassMap{ public ParentMap() { WithTable("Parents"); Id(x => x.Id, "ParentID") .WithUnsavedValue(0) .GeneratedBy.Identity(); Map(x => x.Description, "Description"); HasMany (x => x.Childs) .LazyLoad() .WithKeyColumn("ParentID") .IsInverse() .AsSet(); } } public class ChildMap : ClassMap { public ChildMap() { WithTable("Childs"); Id(x => x.Id, "ChildID") .WithUnsavedValue(0) .GeneratedBy.Identity(); References(x => x.Parent, "ParentID") .CanNotBeNull() .LazyLoad(); } }
正如您所看到的,我已经在关系上设置了LazyLoad.另请注意,在我的模型类中,所有属性都设置为虚拟.
现在进行简单查询:
ICriteria crit = Session.CreateCriteria(typeof(Child)) .Add(Expression.Eq("Id", 18)); IListlist = crit.List ();
并生成SQL:
SELECT this_.ChildID as ChildID5_1_, this_.ParentID as ParentID5_1_, parent2_.ParentID as ParentID4_0_, parent2_.Description as Descript2_4_0_ FROM Childs this_ inner join Parents parent2_ on this_.ParentID = parent2_.ParentID WHERE this_.ChildID = 18 /* @p0 */
如您所见,它在Parent表上进行连接并选择其字段(id和description).但是,为什么我要求延迟加载呢?
现在,如果我将查询更改为:
ICriteria crit2 = Session.CreateCriteria(typeof(Child)) .SetFetchMode("Parent", FetchMode.Lazy) .Add(Expression.Eq("Id", 18));
生成了2个sql查询:
SELECT this_.ChildID as ChildID5_0_, this_.ParentID as ParentID5_0_ FROM Childs this_ WHERE this_.ChildID = 18 /* @p0 */
这对我很好:没有加入,不查询父表.但我也得到了第二个:
SELECT parent0_.ParentID as ParentID4_0_, parent0_.Description as Descript2_4_0_ FROM Parents parent0_ WHERE parent0_.ParentID = 45 /* @p0 */
它再次查询父表.
这两行查询是在行中生成的:
IListlist = crit.List ();
我完全不知道这里发生了什么.有人可以帮忙吗?
这取决于您的Fluent NHibernate版本.直到某个点为止,默认情况下所有实体都不会延迟加载.这相当于lazy="false"
在您的实体中明确设置.现在不再是这种情况了,但是如果你在那之前运行任何事情,那么你会看到这种行为.
多对一/引用延迟加载设置被来自目标的实体级延迟加载覆盖,因此如果您在此旧版本的FNH上运行,则实体设置将使您的References(...).LazyLoad()
调用无意义.
您需要验证您是否使用最新版本的FNH,这应该可以解决问题; 但是,如果没有,那么您需要在Parent
实体中明确设置延迟加载.你可以用上面的LazyLoad
方法做到这一点ClassMap
.