Domanda

Ho una tabella autoreferenziale, che ha ID, ParentID (nullable).

Quindi, la tabella contiene molti nodi, ogni nodo potrebbe essere la radice nella gerarchia (parent è null) o qualsiasi livello della gerarchia (parent esiste altrove nella tabella).

Dato un nodo iniziale arbitrario, esiste un'elegante query linq che restituirà tutti i figli della gerarchia da quel nodo?

Grazie.

È stato utile?

Soluzione

Se vuoi selezionare tutti i figli diretti di un nodo, una semplice query come la seguente dovrebbe fare il lavoro:

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

Se vuoi selezionare tutti i discendenti di un nodo, questo non è possibile con LINQ, perché richiede la ricorsione o uno stack che LINQ (e SQL) non fornisce.

Vedi anche:

Altri suggerimenti

Eccone uno veloce che ho appena scritto:

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;

};

Ma credo che sia possibile utilizzare SQL con un Union ALL.

So che questo è un vecchio post, ma dovresti dare un'occhiata a questa estensione:

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

L'ho usato e funziona alla grande.

Fondamentalmente vado con qualcosa del genere come discusso nel link SO che hai proposto.

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

I CTE sono probabilmente la soluzione migliore, ma per ora vorrei mantenere le cose tutte sullo stesso livello.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top