Вы можете сделать это эффективно в одном запросе, грамматика просто неловкая:
var groups = await db.Parents
.Where(p => p.Id == id)
.Select(p => new
{
P = p,
C = p.Children.OrderBy(c => c.SortIndex)
})
.ToArrayAsync();
// Query/db interaction is over, now grab what we wanted from what was fetched
var model = groups
.Select(g => g.P)
.FirstOrDefault();
Объяснение
асинхронная заметка
Iслучайно здесь использовались расширения async
, которые вы, вероятно, должны использовать, но вы можете избавиться от await
/ async
, если вам нужен синхронный запрос без ущерба для эффективной дочерней сортировки.
Первый блок
По умолчанию все объекты EF, извлеченные из БД, отслеживаются.Кроме того, EF-эквивалент SQL Select
разработан вокруг анонимных объектов, которые вы видите выше.Когда создается анонимный объект, оба объекта, назначенные P
и C
, отслеживаются, это означает, что их отношения отмечаются, и их состояние поддерживается EF Change Tracker.Поскольку C
- это список дочерних элементов в P
, даже если вы не просили, чтобы они были явно связаны в вашем анонимном объекте, EF в любом случае загружает их как эту дочернюю коллекцию, из-за взаимосвязион видит в схеме.
Чтобы узнать больше, вы можете разбить вышеперечисленное на 2 отдельных запроса, загружая только родительский объект, а затем только дочерний список, в совершенно разных вызовах Db.EF Change Tracker заметит и загрузит дочерние элементы в родительский объект для вас.
Второй кусок
Мы обманули EF в возвращении упорядоченных дочерних объектов.Теперь мы берем только родительский объект - его дочерние элементы все равно будут присоединены в том порядке, в котором мы хотели.
Нули и таблицы как наборы
Есть неловкий двухэтапный шагздесь в основном для лучших практик вокруг нулей;он должен делать 2 вещи:
Думайте о вещах в БД как о наборах до тех пор, пока не станет возможным абсолютный последний момент.
Избегайте нулевых исключений.
Другими словами, последний кусок мог бы быть:
var model = groups.First().P;
Но если объект отсутствует в БД, он взорвется сисключение нулевой ссылки. C # 6 представит другую альтернативу - оператор слияния нулевых свойств - так что в будущем вы можете заменить последний кусок на:
var model = groups.FirstOrDefault()?.P;