Entity Framework результаты запроса самоссылающейся сущности являются плоскими и иерархическими

У меня есть самоссылающаяся сущность:

EF Mapping

Когда я запрашиваю эту сущность..

var query = this._context.DispositionPossibilities
    .Where(x => x.AreaID == areaID)
    .Where(x => x.IsActive == true);

.. результирующая коллекция имеет КАЖДЫЙ элемент, возвращаемый из запроса в корне, а затем эти элементы с ParentID идентифицируются внутри дочерних коллекций (из-за свойств навигации).

Я могу удалить их, сделав это:

    // have to ToArray() first because the child entities will be excluded if I don't..
    rValue = query.ToArray();
    // trim off the entities at the root that shouldn't be there..
    rValue = rValue.Where(x => !x.ParentCode.HasValue).ToArray();

.. Но есть ли лучший способ сделать это?

1 ответ

Решение

[РЕДАКТИРОВАТЬ]
Мой оригинал Include Решение ниже не пересекает всю иерархию. Это должно было быть для меня очевидно, но оно вернет только ПЕРВЫЙ уровень иерархии.

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

Тем не менее, я придумал лучший способ убрать некорневые элементы из иерархии:

var subset = new List<DispositionPossibility>();
foreach (var disp in query.OrderBy(x => x.ParentCode).ToArray())
{
    if (!disp.ParentCode.HasValue)
        subset.Add(disp);
    else
        break;
}

Это оказалось на 0,4-7 секунд быстрее, чем первый метод, который я использовал. (Это почти так же хорошо, как метод Include, но на самом деле дает мне все уровни.) Добавление сортировки ASC и выход из цикла сбрасывает.1-25 секунд от моих деревьев элементов 27k.




[Оригинальный (ПЛОХОЙ) ответ]

После того, как я не смотрел на это в течение дня и не возвращался к нему, потребовалось всего 5 секунд, чтобы подумать, как это сделать.

var query = context.DispositionPossibilities
    .Include("ChildDispositions")
    .Where(x => x.AreaID == areaID)
    .Where(x => !x.ParentCode.HasValue)
    .Where(x => x.IsActive == true);

Я запустил профилирование кода, и этот метод работает лучше почти в каждом случае:
- Наиболее заметно для моих самых больших деревьев с 4 уровнями и ~27 400 предметов примерно на 0,73 - 0,83 секунды.
- Для небольших деревьев (<5000) разница была гораздо менее заметна (менее 0,01 - 0,05 секунд)

Другие вопросы по тегам