层次结构问题 -> 用 Linq Join 替换递归?
-
07-07-2019 - |
题
我有一个自引用表,其中有 ID、ParentID(可为空)。
因此,该表包含许多节点,每个节点可以是层次结构中的根(父节点为空),也可以是层次结构的任何级别(父节点存在于表中的其他位置)。
给定一个任意的起始节点,是否有一个优雅的 linq 查询将返回该节点的层次结构的所有子节点?
谢谢。
解决方案
如果你想选择 所有直系子女 对于一个节点,像下面这样的简单查询应该可以完成这项工作:
from item in table
where item.ID == parentID;
select item
如果你想选择 所有后代 对于节点而言,这对于 LINQ 来说是不可能的,因为它需要递归或 LINQ(和 SQL)不提供的堆栈。
也可以看看:
- 堆栈溢出: LINQ to SQL 用于自引用表?
- 代码项目: T-SQL - 如何获取分层表中给定元素的所有后代
- 堆栈溢出: 在 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。
基本上我正在使用你所提供的SO链接中所讨论的类似内容。
public IQueryable GetCategories(Category parent)
{
var cats = (parent.Categories);
foreach (Category c in cats )
{
cats = cats .Concat(GetCategories(c));
}
return a;
}
CTE可能是最好的解决方案,但我现在想把所有东西保持在同一层。
不隶属于 StackOverflow