层次结构问题 -> 用 Linq Join 替换递归?

3

我有一个自引用表,其中包含ID、ParentID(可为空)。

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

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

谢谢。

4个回答

3

是的,我想要所有后代,无论层次结构的级别如何,并希望linq足够聪明以处理它,使用连接或let语句或其他一些魔法。 - Scott Klarenbach
你提出的 LINQ 查询无法获取所有直接子级。Join 或 SelectMany 可以完成任务,但如你所建议的那样,不要使用递归。 - Yannick Motton

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实现。


不要相信在SQL中没有通过递归调用程序来实现这一点是不可能的,除非你进行了一些黑客攻击。 - Yannick Motton
1
这将只遍历树的一个分支。 - Mangesh

1

0

基本上,我会按照你提供的SO链接中讨论的方式进行。

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

公用表达式(CTEs)可能是最好的解决方案,但我现在想把所有东西都保持在同一层级。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接