Проблема с иерархией -> Заменить рекурсию соединением Linq?

StackOverflow https://stackoverflow.com/questions/1435229

  •  07-07-2019
  •  | 
  •  

Вопрос

У меня есть самоссылающаяся таблица, которая имеет ID, ParentID (обнуляемый).

Итак, таблица содержит много узлов, каждый узел может быть корневым в иерархии (parent равно null) или любым уровнем иерархии (parent существует в другом месте таблицы).

Учитывая произвольный начальный узел, существует ли элегантный запрос linq, который вернет все дочерние элементы иерархии из этого узла?

Спасибо.

Это было полезно?

Решение

Если вы хотите выбрать все прямые дети узла, простой запрос, подобный следующему, должен выполнить эту работу:

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

Если вы хотите выбрать все потомки для узла это невозможно с LINQ, поскольку для этого требуется рекурсия или стек, который LINQ (и SQL) не предоставляют.

Смотрите также:

Другие советы

Вот краткое из того, что я только что написал:

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 с Объединением ALL .

Я знаю, что это старый пост, но вы должны ознакомиться с этим расширением:

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

Я использую его, и он отлично работает.

В принципе, я использую что-то вроде этого, как обсуждалось в ссылке SO, которую вы предоставили.

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

CTE, вероятно, являются лучшим решением, но пока я хотел бы сохранить все на одном уровне.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top