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

发布于 2024-08-04 12:12:22 字数 176 浏览 5 评论 0原文

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

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

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

谢谢。

I have a self referential table, which has ID, ParentID (nullable).

So, the table contains many nodes, each node could be the root in the hierarchy (parent is null), or any level of the hierarchy (parent exists elsewhere in the table).

Given an arbitrary starting node, is there an elegant linq query that will return all children of the hierarchy from that node?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

最好是你 2024-08-11 12:12:22

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

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

如果您想选择节点的所有后代,这是对于 LINQ 来说这是不可能的,因为它需要递归或 LINQ(和 SQL)不提供的堆栈。

另请参阅:

If you want to select all direct children of a node, a simple query like the following should do the job:

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

If you want to select all descendants of a node, this is not possible with LINQ, because it requires recursion or a stack which LINQ (and SQL) doesn't provide.

See also:

云雾 2024-08-11 12:12:22

这是我刚刚写的一篇简短的文章:

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 是可能的。

Here is a quick one I just wrote:

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;

};

But I believe it is possible to do using SQL with a Union ALL.

樱&纷飞 2024-08-11 12:12:22

我知道这是一篇旧帖子,但您应该查看此扩展:

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

我一直在使用它,而且效果很好。

I know this is an old post but you should check out this extension:

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

I've been using it and it is working great.

两仪 2024-08-11 12:12:22

基本上我会按照您提供的 SO 链接中讨论的那样进行类似的操作。

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

CTE 可能是最好的解决方案,但我想暂时将所有内容保留在同一层中。

Basically I'm going with something like this as discussed in the SO link you proivded.

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

CTEs are probably the best solution but I'd like to keep things all in the same tier for now.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文