Scott Klarenbach
Scott Klarenbach

Reputation: 38721

Hierarchy Problem -> Replace Recursion with Linq Join?

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.

Upvotes: 3

Views: 5403

Answers (4)

rboarman
rboarman

Reputation: 8214

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.

Upvotes: 1

dtb
dtb

Reputation: 217243

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:

Upvotes: 3

Scott Klarenbach
Scott Klarenbach

Reputation: 38721

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.

Upvotes: 0

Yuriy Faktorovich
Yuriy Faktorovich

Reputation: 68667

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.

Upvotes: 3

Related Questions