我正试图让以下内容起作用:
_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())
修改
进一步观察,
_dbmsParentSections.ForEach(x => x.Children = x.Children.OrderBy(y => y.Order).ToList());
为我完成了这项工作(在最初的Factory
电话之后,没有Children.OrderBy
)。
答案 0 :(得分:36)
您似乎无法在查询中对子集合进行排序。 在查询之后排序或在第二个查询中加载子项。
类似的问题和答案here
答案 1 :(得分:12)
扩展方法Include
仅仅是DbQuery.Include
的包装。在内部,它不会执行表达式,而只是解析它们,即它采用它们的成员表达式并将它们转换为路径作为字符串。该路径用作DbQuery.Include
的输入。
之前已要求增强Include
的功能,例如通过包含Where
子句来允许部分加载的集合。订购可能是另一个变更请求。但正如您所看到的,由于Include
的内部工作,整个机制将不得不重新设计以实现此类增强。我没有在当前的road map上看到它,所以可能需要一段时间......
答案 2 :(得分:11)
根据 this 文档,从 EF Core 5.0 开始,您可以按包含实体的属性进行排序:
await context.Parents
.OrderBy(parent => parent.Order)
.Include(parent => parent.Children.OrderBy(child => child.Order))
.ToListAsync();
以上示例按顺序对父实体进行排序,并按子实体的顺序属性对子实体进行排序。
答案 3 :(得分:1)
这永远不会有效。 EF include试图理解并将所有内容翻译成SQL,但是你想从中得到很多。加载所有实体而不进行排序和.ToList() - 并为IEnumerable编写扩展方法以获得有序结果。
答案 4 :(得分:1)
我使用此代码通过订购包括,使用选择和函数订购集合的代码。 不是最好的,但是如果子集合很小,就可以正常工作
// 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;
}
答案 5 :(得分:0)
通常,如果您使用的是一堆包含,那是因为您需要在视图中访问子属性。我需要在视图中访问它时订购子集合。
例如,我可能会为主/详细信息表单构建一些Include语句。在初始EF查询中排序这是没有意义的。相反,为什么不在实际访问它们时在视图级别订购这些子记录?
我可能会对多个调查问题进行调查。当我将模型子集合传递给局部视图时,如果我想以部分视图级别以特定顺序呈现问题。
@Html.Partial("_ResponsesPartial",Model.SurveyResponses.OrderBy(x =>
x.QuestionId))
答案 6 :(得分:0)
根据用例,您可能不需要加载单独的查询或事后进行排序。
在我的情况下,我需要在视图中循环时对它们进行排序,所以我只在其中进行排序
@foreach (var subObject in Object.SubObjects.OrderBy(x=>x.Order))
答案 7 :(得分:-3)
您不应将IQueryable
类型转换为IEnumerable
并致电Include
,因为Include
类型不支持IEnumerable
。
简而言之,永远不要在ToList
IQueryable = server side call (SQL)
IEnumerable = client side (loaded in memory)