3

我有一个自引用表,它有 ID、ParentID(可为空)。

因此,表包含许多节点,每个节点可以是层次结构中的根(父节点为空),或层次结构的任何级别(父节点存在于表中的其他位置)。

给定一个任意的起始节点,是否有一个优雅的 linq 查询将从该节点返回层次结构的所有子节点?

谢谢。

4

4 回答 4

3

如果你想选择一个节点的所有直接子节点,一个像下面这样的简单查询应该可以完成这项工作:

from item in table
where item.ID == parentID;
select item

如果要选择节点的所有后代,则使用 LINQ 是不可能的,因为它需要递归或 LINQ(和 SQL)不提供的堆栈。

也可以看看:

于 2009-09-16T20:33:48.110 回答
3

这是我刚刚写的一个快速的:

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;

};

但我相信可以将 SQL 与 Union ALL 一起使用。

于 2009-09-16T20:47:27.033 回答
1

我知道这是一篇旧帖子,但你应该看看这个扩展:

http://www.scip.be/index.php?Page=ArticlesNET23

我一直在使用它,它工作得很好。

于 2010-10-22T18:05:04.200 回答
0

基本上,我将使用您提供的 SO 链接中讨论的类似内容。

public IQueryable GetCategories(Category parent)
{
    var cats = (parent.Categories);
    foreach (Category c in cats )
    {
        cats  = cats .Concat(GetCategories(c));
    }
    return a;
}

CTE 可能是最好的解决方案,但我现在想把所有东西都放在同一层。

于 2009-09-16T20:49:00.697 回答