Ответ 1
Кажется, вы не можете сортировать коллекцию детей в своем запросе. Любой из них сортируется после запроса или загружает дочерние элементы во второй запрос.
Подобный вопрос и ответ здесь
Я пытаюсь найти что-то вроде следующего:
_dbmsParentSections = FactoryTools.Factory.PdfSections
.Include(x => x.Children.OrderBy(y => y.Order).ToList())
.Include(x => x.Hint).Include(x => x.Fields)
.Where(x => x.FormId == FormId && x.Parent == null)
.OrderBy(o => o.Order)
.ToList();
Часть, которая вызывает исключение:
.Include(x => x.Children.OrderBy(y => y.Order).ToList())
EDIT:
После дальнейшего наблюдения
_dbmsParentSections.ForEach(x => x.Children = x.Children.OrderBy(y => y.Order).ToList());
выполнил эту работу для меня (после начального вызова Factory
и без Children.OrderBy
).
Кажется, вы не можете сортировать коллекцию детей в своем запросе. Любой из них сортируется после запроса или загружает дочерние элементы во второй запрос.
Подобный вопрос и ответ здесь
Метод расширения Include
является простой оболочкой DbQuery.Include
. Внутренне он не выполняет выражения, а только анализирует их, т.е. Принимает выражения членов и преобразует их в путь как строку. Путь используется как вход для DbQuery.Include
.
Ранее было предложено улучшить функциональность Include
, например. чтобы частично загружать коллекции, включая предложение Where
. Заказ может быть другим запросом на изменение. Но, как вы видите, из-за внутренней работы Include
весь механизм должен быть перепроектирован для реализации таких усовершенствований. Я не вижу его в текущей дорожной карте, поэтому это может занять некоторое время...
Это никогда не будет работать. EF include - это попытка понять и перевести все на SQL, но вы многое хотите от этого. Загрузите все сущности без сортировки и .ToList() - и напишите метод расширения для IEnumerable, чтобы получить упорядоченный результат.
Как правило, если вы используете кучу включений, это связано с тем, что вам нужно получить доступ к дочерним свойствам в представлении. То, что я делаю, это заказать дочернюю коллекцию, когда мне нужно получить к ней доступ в представлении.
Например, я могу создать некоторые инструкции Include для формы master/detail. Там нет смысла упорядочивать это при первоначальном запросе EF. Вместо этого, почему бы не упорядочить эти дочерние записи на уровне представления, когда вы действительно обращаетесь к ним?
У меня может быть опрос с несколькими вопросами опроса. Если я хочу представить вопросы в определенном порядке, сделайте это на уровне частичного представления, когда я передаю дочернюю коллекцию модели на частичный вид.
@Html.Partial("_ResponsesPartial",Model.SurveyResponses.OrderBy(x =>
x.QuestionId))
Я использую этот код для заказа включения, используя select и функцию для упорядочивания коллекции. Не самый лучший, но работает нормально, если небольшой сбор
// GET: api/Tareas
[HttpGet]
public IEnumerable<Tarea> GetTareas()
{
var result = _context.Tareas
.Include(p => p.SubTareas)
.Select(p => SortInclude(p));
return result;
}
private Tarea SortInclude(Tarea p)
{
p.SubTareas = (p.SubTareas as HashSet<SubTarea>)?
.OrderBy(s => s.Position)
.ToHashSet<SubTarea>();
return p;
}
В зависимости от варианта использования вам может не потребоваться загрузка в отдельном запросе или сортировка впоследствии.
В моем случае мне нужно было их заказывать при зацикливании в представлении, поэтому я просто заказал там
@foreach (var subObject in Object.SubObjects.OrderBy(x=>x.Order))
Вам не следует преобразовывать тип IQueryable
в IEnumerable
и вызывать Include
, потому что Include
не поддерживается типом IEnumerable
.
Короче говоря, никогда не вызывайте Include после ToList
IQueryable = server side call (SQL)
IEnumerable = client side (loaded in memory)