C# 使用Linq对实体进行分组和多重排序
我有两个实体:C# 使用Linq对实体进行分组和多重排序,c#,linq,linq-to-entities,ef-code-first,C#,Linq,Linq To Entities,Ef Code First,我有两个实体: public class Course { public int Id { get; set; } public string Name { get; set; } public DateTime StartDate { get; set; } public DateTime EndDate { get; set; } public virtual ICollection<Class> Classes { get; set; }
public class Course
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public virtual ICollection<Class> Classes { get; set; }
}
public class Class
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; } ]
public Course Course { get; set; }
}
但是我不能在开始的时候安排好每一节课。我试过这个:
var myList = context.Classes
.OrderBy(c => c.StartTime)
.GroupBy(c => c.Course)
.OrderByDescending(g => g.Key.StartDate).ToList()
即使这样:
var myList = context.Classes
.GroupBy(c => c.Course)
.OrderByDescending(g => g.Key.StartDate)
.ThenBy(g => g.Select(c => c.StartTime)).ToList()
但是这些课程从来都不是按开始时间排序的
*编辑以获得更好的澄清:
这是针对一个Web服务的,我必须返回一个列表
,我真的需要一种优雅的方法来实现这一点(即只使用Linq),而不需要手动创建列表。当然,除非这是不可能的
非常感谢您的帮助(我使用的是EF code first 4.3 btw)。看起来您真的需要一个列表列表,其中每个嵌套列表都按照您提到的其他条件排序。由于您是按
课程进行分组的
,因此您可以按开始日期对组进行排序,因为组中的每个条目都有相同的开始日期。然后可以将分组的元素投影到按开始时间排序的列表中:
var myList = context.Classes
.GroupBy(c => c.Course)
.OrderByDescending(g => g.Key.StartDate)
.Select(g => g.OrderBy(c => c.StartTime).ToList())
.ToList();
由于EF创建直接SQL,因此不可能在同一SQL中进行包含排序的分组 我建议在一个Linq语句中使用EF进行分组,并以ToList()结尾。然后使用Linq对对象(内存中)进行排序,作为第二个Linq语句 因为对象已经分组,所以应该运行得很快 因此,类似的方法应该有效:
var myList = context.Classes
.GroupBy(c => c.Course).ToList()
.OrderByDescending(g => g.Key.StartDate).ToList()
如果您需要保留签名,我建议如下:
var myList = context.Classes
.GroupBy(cc => cc.Course)
.OrderByDescending(gg => gg.Key.StartDate)
.ToArray() // <- stops EF and starts L2O
.SelectMany(gg => gg.OrderBy(cc => cc.StartTime))
.ToLookup(cc => cc.Course, cc => cc)
.ToList();
var myList=context.class
.GroupBy(cc=>cc.Course)
.OrderByDescending(gg=>gg.Key.StartDate)
.ToArray()//gg.OrderBy(cc=>cc.StartTime))
.ToLookup(cc=>cc.Course,cc=>cc)
.ToList();
这将产生一种签名类型:
List
,并按StartTime
对其进行正确排序。这取决于ToLookup
在维护找到的订单方面的行为,可能会发生更改。问题是我确实需要返回列表。这是一个Web服务,我不能修改消费者。否则,我只需在客户机上执行foreach(group.OrderBy(c=>c.StartTime)的var类,但遗憾的是我不能。这可能是您最好的选择。ToLookup
返回一个ILookup
,它实现了IEnumerable
,这意味着您可以将其传递给Web服务(你可能必须投下它,但这不应该是一个问题)。我用一个黑客的变通方法解决了它,但这更优雅。
var myList = context.Classes
.GroupBy(cc => cc.Course)
.OrderByDescending(gg => gg.Key.StartDate)
.ToArray() // <- stops EF and starts L2O
.SelectMany(gg => gg.OrderBy(cc => cc.StartTime))
.ToLookup(cc => cc.Course, cc => cc)
.ToList();