0

カテゴリ メニューを作成するには、いくつかのツリー階層にデータを入力し、それらをトラバースする必要があります。各カテゴリは、複数の親を持つことができます。問題は、これを効率的に行う方法と、問題を回避するSelect N+1方法です。

現在、2 つのテーブル/エンティティを使用して実装されています。

Category
--------
ID
Title

CategoryLink
---------
ID
CategoryID
ParentID

理想的には、通常のオブジェクト トラバーサルを使用してノードを通過します。つまり、 を通過するCategory.ChildCategoriesなどです。これを 1 つの SQL ステートメントで実行することは可能ですか? また、これはNHibernateで行うことができますか?

4

2 に答える 2

0

これにより、すべてのカテゴリとその子が取得されます。

var result = session.Query<Category>()
                    .FetchMany(x => x.ChildCategories)
                    .ToList();

問題は、ルートカテゴリが何であるかを判断することです。フラグを使用するか、逆コレクション(ParentCategories)をマップして、次のようにすることができます。

var root = session.Query<Category>()
                  .FetchMany(x => x.ChildCategories)
                  .FetchMany(x => x.ParentCategories)
                  .ToList()
                  .Where(x => !x.ParentCategories.Any());

すべての並べ替えはクライアント側で行う必要があります(つまり、後ToList

于 2012-07-06T16:43:21.880 に答える
0

マッピングで abatch-sizeを指定します。Category.ChildCategoriesこれにより、NHibernate は一度に 1 つずつではなく、指定されたサイズのバッチで子を取得します (これにより、N+1 問題が軽減されます)。

ファイルを使用している場合は、次のよう.hbmに指定できます。batch-size

<bag name="ChildCategories" batch-size="30">

または流暢なマッピングを使用する

HasMany(x => x.ChildCategories).KeyColumn("ParentId").BatchSize(30);

詳細については、NHibernate のドキュメントを参照してください。

編集

わかりました、私はあなたの要件を理解していると思います. 次の構成で

HasManyToMany<Item>(x => x.ChildCategories)
    .Table("CategoryLink")
    .ParentKeyColumn("ParentId")
    .ChildKeyColumn("CategoryID")
    .BatchSize(100)
    .Not.LazyLoad()
    .Fetch.Join();

次の行を使用して、1 回の呼び出しで階層全体を取得できるはずです。

var result = session.CreateCriteria(typeof(Category)).List();

何らかの理由で、このような単一のカテゴリを取得する

var categoryId = 1;
var result = session.Get<Category>(categoryId);

階層内のレベルごとに 1 つの呼び出しが発生します。これでもデータベースへの呼び出し回数は大幅に減ると思いますが、データベースへの 1 回の呼び出しで上記の例を動作させることはできませんでした。

于 2012-07-04T16:38:16.787 に答える