簡體   English   中英

使用 Linq 對實體進行分組和多重排序

[英]Grouping and multiple orderings using Linq to Entities

我有這兩個實體:

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; }
}

現在我需要列出每個 Class 按課程分組並按(降序)Course.StartDate 然后按 Class.StartTime 排序。 我可以按課程分組並按課程開始日期排序:

var myList = context.Classes
    .GroupBy(c => c.Course)
    .OrderByDescending(g => g.Key.StartDate).ToList()

但是也無法通過它的 StartTime 來訂購每個 Class。 我試過這個:

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()

但是類從來沒有按它的開始時間排序。

*編輯以便更好地說明:這是針對 WebService 的,我必須返回一個List<IGrouping<Course, Class>>並且我真的想要一種優雅的方式來執行此操作(即僅使用 Linq),而無需手動創建列表。 當然,除非不可能。

感謝任何幫助(順便說一句,我使用的是 EF 代碼優先 4.3)。

看起來你真的需要一個 list of lists ,其中每個嵌套列表都按照你提到的附加條件排序。 由於您按Course分組,因此您可以按開始日期對進行排序,因為組中的每個條目都將具有相同的開始日期。 然后您可以將分組的元素投影到按開始時間排序的列表中:

var myList = context.Classes
    .GroupBy(c => c.Course)
    .OrderByDescending(g => g.Key.StartDate)
    .Select(g => g.OrderBy(c => c.StartTime).ToList())
    .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();

這會產生一種簽名類型: List<IGrouping<Course, Class>>並讓它們按StartTime正確排序。 這依賴於ToLookup在維護找到的順序方面的行為,並且可能會發生變化。

由於 EF 直接創建 SQL,因此不可能進行包含同一 SQL 中的排序的分組。

我建議使用 EF 在一個 Linq 語句中進行分組,並以 ToList() 結尾。 而不是使用 Linq To Objects(在內存中)作為第二個 Linq 語句進行排序。

這應該運行得很快,因為對象已經分組。

所以這樣的事情應該有效:

var myList = context.Classes
    .GroupBy(c => c.Course).ToList()
    .OrderByDescending(g => g.Key.StartDate).ToList()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM