我有一个Parent类,它有两个子集合ChildCollectionA和ChildCollectionB。 ChildCollectionA被映射为关联,并具有自己的ID:
HasMany(parent => parent.ChildCollectionA)
.KeyColumn("IDParent")
.AsBag().Cascade.AllDeleteOrphan();
和ChildCollectionB映射有一个组件列表:
HasMany(parent => parent.ChildCollectionB)
.Table("ChildCollectionBTable")
.KeyColumn("IDParent")
.Component(m=>
{
m.References(childB => childB.Task, "IDTask").Not.LazyLoad().Not.Nullable();
m.Map(childB => childB.Date, "Date").Not.Nullable();
}
)
.AsBag().Cascade.AllDeleteOrphan();
我现在需要DataBase中的所有Parent,因为我必须执行一些需要ChildCollectionA和ChildCollectionB的操作。
所以我不得不急于加载它们,我使用了获取模式来急切加载ChildCollectionA:
var queryParents = session.CreateCriteria() .SetFetchMode(“ChildCollectionA”,FetchMode.Eager) 。新增(Expression.Le( “ParentDate”,结束日期));
它返回492个父母(应该是481),我执行的操作的总价值是32,847.46€(应该是30,790.87€)。所以我必须消除父副本:
var queryParents = session.CreateCriteria<Parent>()
.SetFetchMode("ChildCollectionA", FetchMode.Eager)
.Add(Expression.Le("ParentDate",endDate))
.SetResultTransformer(new DistinctRootEntityResultTransformer());
我只用ChildCollectionB
尝试了同样的热切加载var queryParents = session.CreateCriteria<Parent>()
.SetFetchMode("ChildCollectionB", FetchMode.Eager)
.Add(Expression.Le("ParentDate",endDate))
.SetResultTransformer(new DistinctRootEntityResultTransformer());
在这两种情况下,481个父母都可以回复,价值是30,790.87€OK。
但是我需要同时加载两个集合,我这样做了:
var queryParents = session.CreateCriteria<Parent>()
.SetFetchMode("ChildCollectionA", FetchMode.Eager)
.SetFetchMode("ChildCollectionB", FetchMode.Eager)
.Add(Expression.Le("ParentDate",endDate))
.SetResultTransformer(new DistinctRootEntityResultTransformer());
它回报了481名父母,价值为32,602.57欧元(应该是30,790.87欧元)。
现在返回的父项数是正确的,但在其他地方有重复项,值取决于集合而不是父项,因此重复项必须位于ChildCollections中的某处。
现在我正在使用一个丑陋的解决方案:
var queryParents = session.CreateCriteria<Parent>()
.SetFetchMode("ChildCollectionA", FetchMode.Eager)
.Add(Expression.Le("ParentDate",endDate))
.SetResultTransformer(new DistinctRootEntityResultTransformer());
parents= queryParents.List<Parent>();
foreach (Parent p in parents)
{
NHibernateUtil.Initialize(p.ChildCollectionB);
}
它回来了481个父母,价值是30,790.87€OK。
问题发生在我急切加载两个集合时,如果我急切加载一个,然后强制lazyload到另一个,它的工作。我不知道ChildCollectionB作为组件列表而不是关联的映射是否与此有关...
任何线索?
由于
答案 0 :(得分:4)
我认为问题是两个集合之间的笛卡尔积不是由DistinctRootEntityTransformer处理的...所以你在某处的集合中会有重复的数据。
要急切地加载多个集合,它将需要多次查询。
var queryParents = session.CreateCriteria<Parent>()
.SetFetchMode("ChildCollectionA", FetchMode.Eager)
.Add(Expression.Le("ParentDate",endDate))
.SetResultTransformer(new DistinctRootEntityResultTransformer());
//load CollectionB in second query...it's linked together by NH
session.CreateCriteria<Parent>()
.SetFetchMode("ChildCollectionB", FetchMode.Eager)
.Add(Expression.Le("ParentDate",endDate))
.List();
我通常做的是获取主要实体以及所有必需的多对一关联。然后,我将急切地将所需的集合提取到具有MultiCriteria的会话中。如果它只有两个集合,我有时会喜欢上面的东西并获取具有distinctrootentity的第一个集合。
有关详细信息,请参阅Eager loading aggregate with many child collections