我有一个需要加载名为Node的复杂对象的要求……其实它并不是那么复杂……看起来像这样:
Node引用了EntityType,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对象中,不使用Lazy load。原因是我的数据库中有成千上万个Node对象,我必须使用WCF服务将它们发送到网络。我遇到了SQL N+1问题。我正在使用Fluent Nhibernate和Automapping,并且NHibernate Profiler建议我使用FetchMode.Eager一次性加载整个对象。我正在使用以下查询:
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 也是如此。因此,我想知道如何修改上述查询以返回所有唯一的 Nodes 及其中的属性和 Listvalues。