考虑以下模型:
pivot_table
当我使用LINQ to Entities检索一个或多个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;
}
}
对象时,我希望将Form
对象的关联集合按Section
属性排序。此外,在每个SortOrder
个对象中,我希望以相同的方式对相关的Section
对象集合进行排序。
我不记得我在哪里阅读它,但是我能够使用类似于以下内容的LINQ查询来获得第一级排序:
Question
从那里,我可以使用类似的东西来获取实际的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
我无法弄清楚如何编写LINQ查询以将此行为扩展到第二级集合(每个var form = query.ToList().Select(q => q.Root).FirstOrDefault();
对象中的Question
个对象的集合。
*更新*
请参阅我对Ivan的评论,其中解释了这个问题是如何重复的。
答案 0 :(得分:3)
要实现您的需求,您可以使用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
。
你也可以在内存中对导航属性进行排序,就像@IvanStoev引用的post中的解决方案一样,但是如果你想以某种顺序引入相关实体,过滤掉其他操作,你可以考虑使用Explicit Loading:
foreach f in context.Form
{
context.Entry(f).Collection(r => r.Sections)
.Query().OrderBy(s=>s.SortOrder)
.Load();
}
但恕我直言,最好的解决方案是创建自定义类(也称为DTOs)以投影所需的结果,仅加载一次往返所需的数据
答案 1 :(得分:2)
考虑到您直接查询整个表格集,那么您不需要使用方法Eager Loading
.Include()
。
这是一种lambda表达式,通过明确映射属性/列来解决这个问题。
// TODO: replace the null value with a real context DbSet<Form>
IQueryable<Form> forms = null;
var form = forms.Select(x => new Form()
{
Id = x.Id,
Sections = x.Sections.OrderBy(s => s.SortOrder).Select(s => new Section()
{
Id = s.Id,
SortOrder = s.SortOrder,
Questions = s.Questions.OrderBy(q => q.SortOrder).Select(q => new Question()
{
Id = q.Id,
SortOrder = q.SortOrder
}).ToList()
}).ToList()
}).FirstOrDefault();