25

ノードと呼ばれる複雑なオブジェクトをロードする必要があります...それほど複雑ではありません...次のようになります:-

ノードには、プロパティを持つ1対多を持つEntityTypeへの参照があり、プロパティは、PorpertyListValueを持つ1対多です。

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オブジェクトにすべての子オブジェクトを一度にロードすることです。遅延読み込みはありません。その理由は、データベースに数千のノードオブジェクトがあり、WCFサービスを使用してそれらをネットワーク経由で送信する必要があるためです。クラスSQL N+1の問題が発生しました。私は自動マッピングでFluentNhibernateを使用していますが、NHibernate Profilerは、FetchMode.Eagerを使用してオブジェクト全体を一度にロードすることを提案しました。私は次のqyueryを使用しています

     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がオブジェクトにプロパティをロードされていません。実際、返されるノード数はクエリの行数と等しいため、ノードオブジェクトが繰り返されます。さらに、各ノード内のプロパティが繰り返され、リスト値も繰り返されます。

したがって、上記のクエリを変更して、プロパティとリスト値を含むすべての一意のノードを返す方法を知りたいと思います。

4

4 に答える 4

23

各マッピングでは遅延読み込みをオフにする必要があります

ノードマップ内:

Map(x => x.EntityType).Not.LazyLoad();

EnityTypeマップ:

Map(x => x.Properties).Not.LazyLoad();

等々...

また、NHibernateEagerがマルチレベルの子オブジェクトを1回だけ積極的に読み込むことをご覧ください。

追加した:

SQL N + 1に関する追加情報:

http://nhprof.com/Learn/Alerts/SelectNPlusOne

于 2010-06-29T18:27:27.873 に答える
14

私はそれを自分で理解します。重要なのは、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/nhusers@googlegroups.com/2010-05/msg00512.html

http://ayende.com/Blog/archive/2010/01/16/eagerly-loading-entity-associations-efficiently-with-nhibernate.aspx

于 2010-08-18T09:50:57.253 に答える
9

私は次のようなものになりました:

HasMany(x => x.YourList).KeyColumn("ColumnName").Inverse().Not.LazyLoad().Fetch.Join()

結合による重複を避けるために、必ず次のようにエンティティを選択してください。

session.CreateCriteria(typeof(T)).SetResultTransformer(Transformers.DistinctRootEntity).List<T>();
于 2011-10-12T19:09:38.480 に答える
4

DistinctRootEntityResultTransformerを指定したSetResultTransformerは、メインオブジェクトに対してのみ機能しますが、IListコレクションは乗算されます。

于 2010-12-21T20:16:34.903 に答える