Как Entity Framework работает с рекурсивными иерархиями? Включить (), кажется, не работает с ним - PullRequest
67 голосов
/ 20 августа 2009

У меня есть Item. Item имеет Category.

Category имеет ID, Name, Parent и Children. Parent и Children тоже относятся к Category.

Когда я выполняю запрос LINQ to Entities для определенного Item, он не возвращает связанный Category, если я не использую метод Include("Category"). Но это не приносит полную категорию, с ее родителями и детьми. Я мог бы сделать Include("Category.Parent"), но этот объект похож на дерево, у меня рекурсивная иерархия, и я не знаю, где он заканчивается.

Как сделать так, чтобы EF полностью загружал Category с родителями и детьми, а родитель с их родителями и детьми и т. Д.?

Это не что-то для всего приложения, из соображений производительности оно потребуется только для этой конкретной сущности, категории.

Ответы [ 12 ]

0 голосов
/ 14 сентября 2017

@ парламент дал мне идею для EF6. Пример для категории с методами для загрузки всех родителей до корневого узла и всех дочерних элементов.

ПРИМЕЧАНИЕ: Используйте это только для операций, не критичных к производительности. Пример с производительностью 1000 узлов от http://nosalan.blogspot.se/2012/09/hierarchical-data-and-entity-framework-4.html.

Loading 1000 cat. with navigation properties took 15259 ms 
Loading 1000 cat. with stored procedure took 169 ms

Код:

public class Category 
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public string Name { get; set; }

    public int? ParentId { get; set; }

    public virtual Category Parent { get; set; }

    public virtual ICollection<Category> Children { get; set; }

    private IList<Category> allParentsList = new List<Category>();

    public IEnumerable<Category> AllParents()
    {
        var parent = Parent;
        while (!(parent is null))
        {
            allParentsList.Add(parent);
            parent = parent.Parent;
        }
        return allParentsList;
    }

    public IEnumerable<Category> AllChildren()
    {
        yield return this;
        foreach (var child in Children)
        foreach (var granChild in child.AllChildren())
        {
            yield return granChild;
        }
    }   
}
0 голосов
/ 22 июня 2012

попробуйте

List<SiteActionMap> list = this.GetQuery<SiteActionMap>()
                .Where(m => m.Parent == null && m.Active == true)
                .Include(m => m.Action)
                .Include(m => m.Parent).ToList();    

if (list == null)
    return null;

this.GetQuery<SiteActionMap>()
    .OrderBy(m => m.SortOrder)
    .Where(m => m.Active == true)
    .Include(m => m.Action)
    .Include(m => m.Parent)
    .ToList();

return list;
...