考虑以下模型:
public class Form
{
public Guid Id
{
get;
set;
}
public List<Section> Sections
{
get;
set;
}
}
public class Section
{
public Guid Id
{
get;
set;
}
public List<Question> Questions
{
get;
set;
}
public int SortOrder
{
get;
set;
}
}
public class Question
{
public Guid Id
{
get;
set;
}
public int SortOrder
{
get;
set;
}
}
当我使用 LINQ to Entities 检索一个或多个 Form 对象时,我希望相关联的 Section 对象集合按 SortOrder属性。此外,在每个 Section 对象中,我希望以相同的方式对相关的 Question 对象集合进行排序。
我不记得我是在哪里读到它的,但我已经能够使用类似于以下内容的 LINQ 查询来进行一级排序:
var query =
from
f in context.Form
where
f.Id == *some form id*
select
new
{
Root = f,
Sections = f.Sections.OrderBy(s => s.SortOrder)
};
从那里,我可以通过使用类似的东西获得实际的 Form 对象:
var form = query.ToList().Select(q => q.Root).FirstOrDefault();
我想不通的是如何编写 LINQ 查询以将此行为向下扩展到二级集合(每个 Section 对象中的 Question 对象的集合.
* 更新 *
请参阅下面我对 Ivan 的评论,其中解释了为什么这个问题不是重复的。
请您参考如下方法:
要实现您需要的功能,您可以使用 Eager Loading :
var query= from f in context.Form.Include(f=>f.Sections.Select(s=>s.Questions))
where f.Id == *some form id*
select
new
{
Root = f,
Sections = f.Sections
.OrderBy(s => s.SortOrder)
.Select(s=> new{s.Id, s.SortOrder, Questions=s.Questions.OrderBy(q=>q.SortOrder)})
};
Include扩展方法允许您将相关实体作为查询的一部分包括在内,甚至是更深的层次(查看我上面引用的 link 中的 备注 部分)。
第二种解决方案可能是使用 Lazy Loading ,如果你没有禁用这个功能,默认情况下是启用的,你需要满足一些requirements例如,要使用,您的导航属性必须是 virtual。
更新
您还可以像 post 中的解决方案一样对内存中的导航属性进行排序这是@IvanStoev 引用的,但如果您想按某种顺序带来相关实体,过滤等操作,您可以考虑使用 Explicit Loading :
foreach f in context.Form
{
context.Entry(f).Collection(r => r.Sections)
.Query().OrderBy(s=>s.SortOrder)
.Load();
}
但是恕我直言,最好的解决方案是创建自定义类(也称为 DTOs )来投影所需的结果,以便在一次往返中仅加载您需要的数据
