階層の問題->再帰をLinq Joinに置き換えますか?
-
07-07-2019 - |
質問
ID、ParentID(nullable)を持つ自己参照テーブルがあります。
したがって、テーブルには多くのノードが含まれ、各ノードは階層のルート(親はnull)、または階層の任意のレベル(親はテーブルのどこかに存在します)になります。
任意の開始ノードを指定すると、そのノードから階層のすべての子を返すエレガントなlinqクエリがありますか?
ありがとう。
解決
ノードのすべての直接の子を選択する場合は、次のような簡単なクエリを実行する必要があります。
from item in table
where item.ID == parentID;
select item
ノードのすべての子孫を選択する場合、LINQ(およびSQL)が提供しない再帰またはスタックが必要なため、これはLINQでは不可能です。
参照:
- StackOverflow:自己参照テーブルのLINQ to SQL?
- CodeProject: T-SQL-特定の要素のすべての子孫を取得する方法階層テーブル
- StackOverflow: LINQでの再帰の表現
他のヒント
これは私が書いた簡単なものです:
class MyTable
{
public int Id { get; set; }
public int? ParentId { get; set; }
public MyTable(int id, int? parentId) { this.Id = id; this.ParentId = parentId; }
}
List<MyTable> allTables = new List<MyTable> {
new MyTable(0, null),
new MyTable(1, 0),
new MyTable(2, 1)
};
Func<int, IEnumerable<MyTable>> f = null;
f = (id) =>
{
IEnumerable<MyTable> table = allTables.Where(t => t.Id == id);
if (allTables
.Where(t => t.ParentId.HasValue && t.ParentId.Value == table
.First().Id).Count() != 0)
return table
.Union(f(
allTables.Where(t => t.ParentId.HasValue && t.ParentId.Value == table
.First().Id).First().Id));
else return table;
};
しかし、Union ALLでSQLを使用することは可能だと思います。
これは古い投稿ですが、この拡張機能を確認する必要があります:
http://www.scip.be/index.php?Page=ArticlesNET23
私はそれを使用してきましたが、うまく機能しています。
基本的には、提供したSOリンクで説明したように、このようなものを使用します。
public IQueryable GetCategories(Category parent)
{
var cats = (parent.Categories);
foreach (Category c in cats )
{
cats = cats .Concat(GetCategories(c));
}
return a;
}
CTEはおそらく最良のソリューションですが、現時点ではすべてを同じ階層に維持したいと思います。
所属していません StackOverflow