使用LINQ to Entities对多个子集合级别进行排序

时间:2016-03-15 20:10:09

标签: c# entity-framework linq sorting

考虑以下模型:

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的评论,其中解释了这个问题是如何重复的。

2 个答案:

答案 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();