【发布时间】:2010-06-29 16:48:32
【问题描述】:
我需要加载一个名为 Node 的复杂对象……嗯,它并不复杂……如下所示:-
Node 具有对 EntityType 的引用,该引用具有 一对多 和 Property,而 Property 又具有一对多与PorpertyListValue
public class Node
{
public virtual int Id
{
get;
set;
}
public virtual string Name
{
get;
set;
}
public virtual EntityType Etype
{
get;
set;
}
}
public class EntityType
{
public virtual int Id
{
get;
set;
}
public virtual string Name
{
get;
set;
}
public virtual IList<Property> Properties
{
get;
protected set;
}
public EntityType()
{
Properties = new List<Property>();
}
}
public class Property
{
public virtual int Id
{
get;
set;
}
public virtual string Name
{
get;
set;
}
public virtual EntityType EntityType
{
get;
set;
}
public virtual IList<PropertyListValue> ListValues
{
get;
protected set;
}
public virtual string DefaultValue
{
get;
set;
}
public Property()
{
ListValues = new List<PropertyListValue>();
}
}
public class PropertyListValue
{
public virtual int Id
{
get;
set;
}
public virtual Property Property
{
get;
set;
}
public virtual string Value
{
get;
set;
}
protected PropertyListValue()
{
}
}
我试图做的是一次加载所有子对象的 Node 对象。没有延迟加载。原因是我在数据库中有数千个 Node 对象,我必须使用 WCF 服务通过网络发送它们。我遇到了类 SQL N+1 问题。我正在使用 Fluent Nhibernate 和 Automapping,NHibernate Profiler 建议我使用 FetchMode.Eager 一次加载整个对象。我正在使用以下 qyuery
Session.CreateCriteria(typeof (Node))
.SetFetchMode( "Etype", FetchMode.Join )
.SetFetchMode( "Etype.Properties", FetchMode.Join )
.SetFetchMode( "Etype.Properties.ListValues", FetchMode.Join )
或者使用 NHibernate LINQ
Session.Linq<NodeType>()
.Expand( "Etype")
.Expand( "Etype.Properties" )
.Expand( "Etype.Properties.ListValues" )
当我运行上述任何查询时,它们都会生成一个包含所有左外连接的相同查询,这正是我所需要的。但是,由于某种原因,查询返回的 IList 没有被加载到对象中。实际上返回的Nodes计数等于查询的行数,因此Nodes对象是重复的。此外,每个Node中的属性都是重复的,Listvalues也是如此。
所以我想知道如何修改上述查询以返回所有唯一节点及其属性和列表值。
【问题讨论】:
-
在谷歌上我发现了 DistinctRootEntityResultTransformer 但这只能解决 Root 对象的问题。我仍然在子集合中得到重复。返回列表中的每个根对象在具有相同实体的多个实例的子集合中都有一些奇怪的笛卡尔积混乱。任何的想法?等待纳比尔
-
我想我已经找到了解决方案,但我想知道它是否正确。根对象(节点)内的子集合(EType.Properties、Etype.Properties.ListValues)是 IList。我在文档中读到 IList 可以包含重复项,因此如果我将 IList 更改为 ISet/ICollection,则查询不会在子集合中加载重复实例。但是这个解决方案需要大量的重构。我想知道是否有一种方法可以将 IList 用于子集合?等待着,纳比尔
-
我有同样的问题(使用 Fetchmode.Eager)。我对 NHibernate 对此感到非常失望。我宁愿出错也不愿数据不正确。
标签: nhibernate fluent-nhibernate eager-loading automapping