Node ...という複雑なオブジェクトをロードする必要があります。それほど複雑ではありません...次のようになります:-
NodeにはEntityTypeへの参照があり、これには1対多とプロパティこれは1対多で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の問題が発生しました。自動マッピングでFluentNhibernateを使用しており、NHibernate Profilerで使用するように提案されましたFetchMode.Eager =オブジェクト全体を一度にロードする次のSQLを使用しています
Session.CreateCriteria(typeof (Node))
.SetFetchMode( "Etype", FetchMode.Join )
.SetFetchMode( "Etype.Properties", FetchMode.Join )
.SetFetchMode( "Etype.Properties.ListValues", FetchMode.Join )
またはNHibernateLINQを使用する
Session.Linq<NodeType>()
.Expand( "Etype")
.Expand( "Etype.Properties" )
.Expand( "Etype.Properties.ListValues" )
上記のクエリのいずれかを実行すると、両方とも、すべての左側の外部結合を含む1つの同じ単一のクエリを生成します。これが必要です。ただし、何らかの理由で、クエリから返されるIListがオブジェクトにプロパティをロードされていません。実際、返されるノード数はクエリの行数と等しいため、ノードオブジェクトが繰り返されます。さらに、各Node内のプロパティが繰り返され、リスト値も繰り返されます。
したがって、上記のクエリを変更して、プロパティとリスト値を含むすべての一意のノードを返す方法を知りたいと思います。
私はそれを自分で理解します。重要なのは、SetResultTransformer()を使用して、DistinctRootEntityResultTransformerのオブジェクトを次のように渡すことです。パラメータ。したがって、クエリは次のようになります。
Session.CreateCriteria(typeof (Node))
.SetFetchMode( "Etype", FetchMode.Join )
.SetFetchMode( "Etype.Properties", FetchMode.Join )
.SetFetchMode( "Etype.Properties.ListValues", FetchMode.Join )
.SetResultTransformer(new DistinctRootEntityResultTransformer());
私はこれらのリンクを通して私の質問への答えを見つけました:
http://www.mailinglistarchive.com/html/[email protected]/2010-05/msg00512.html
各マッピングでは遅延読み込みをオフにする必要があります
in Node Map:
Map(x => x.EntityType).Not.LazyLoad();
enityTypeマップ内:
Map(x => x.Properties).Not.LazyLoad();
等々...
また、 NHibernate Eagerがマルチレベルの子オブジェクトをロードする を参照してください。
追加:
SQL N + 1に関する追加情報:
私は次のようなものになりました:
HasMany(x => x.YourList).KeyColumn("ColumnName").Inverse().Not.LazyLoad().Fetch.Join()
結合による重複を避けるために、必ず次のようにエンティティを選択してください。
session.CreateCriteria(typeof(T)).SetResultTransformer(Transformers.DistinctRootEntity).List<T>();
DistinctRootEntityResultTransformerを指定したSetResultTransformerは、メインオブジェクトに対してのみ機能しますが、IListコレクションは乗算されます。