2012-05-03 10 views
1

私はネストされた構造を持っています。再帰の代わりにlinqのサブクエリ

クラスのページはすべてのサブカテゴリでChildPages私はすべての製品のサンプル(タイプ==「製品」)の要求を取得する必要があります取得する必要がある

class Page 
{ 
IQueryable<Page> ChildPages; 
string type; //catalog or product 
} 

(タイプ==「カタログ」を持っています)

ループや再帰で簡単に実行できます。ただし、多くの時間とリソースが必要です

+4

あなたは、「ページ」、「ChildPage」、「製品」、「カタログ」の単語を使用し、そして「サブカテゴリ」1人の関係を記述するために、私は、私はかなり混乱していると告白しました。 –

+2

あなたの質問には、少し明確にするために「リファクタリング」が必要です。 –

+0

あなたは再帰やループなしでこれを行うことはできません。どんな深さで子孫の子ページをもらうにはどうしたらいいですか? –

答えて

1

EFではサポートされていないと思われますが、再帰的なCTEクエリを使用して、1回のデータベース呼び出しでツリー全体を取得できます。

0

再帰的にLINQを行うには、私が知っている唯一の方法は、不動点演算子を使用することです(下記参照)

しかし、私はある、(@erikkallen答えを参照)EFは、CTEのクエリにこれを変換することができないだろう私は1つのステートメントで再帰的クエリを行うことを知っている唯一の方法です。

class Page 
{ 
    IQueryable<Page> ChildPages; 
    string type; //catalog or product 

    // the query 
    static IQueryable<Page> GetProductsWithCatalogAncestor(IQueryable<Page> pages) 
    { 
     return FixPoint<bool, IQueryable<Page>, IQueryable<Page>> 
      (processChildPages => (hasCatalogAncestor, thePages) 
       => thePages.SelectMany(p => (hasCatalogAncestor && p.type == "product") 
        ? new[] { p }.AsQueryable() 
        : processChildPages(hasCatalogAncestor || p.type == "catalog", p.ChildPages))) 
        (false, pages); 
    } 

    // Generic FixPoint operator 
    static Func<T1, T2, TResult> FixPoint<T1, T2, TResult>(Func<Func<T1, T2, TResult>, Func<T1, T2, TResult>> f) 
    { 
     return (t1, t2) => f(FixPoint(f))(t1, t2); 
    } 
} 
-1

SelectMany()を使用して階層を平坦化してみてください。

var data = pages.SelectMany(p=>p.ChildPages) 
       .Where(p=>p.type == "product" || p.type == "catalog"); 
関連する問題