2017-07-07 91 views
0

我目前正在研究ASP.NET MVC 4.5中的應用程序。我需要編寫一個LINQ查詢來按不同的StatusIds列出項目列表。C#LINQ OrderBy幾個子句

給出的項目與此視圖模型的列表:

public class ProjectVm 
{ 
    public int ProjectId { get; set; } 
    public string Title { get; set; } 
    public Status StatusId { get; set; } 
} 

我的項目狀態枚舉:

public enum Status : byte 
{ 
    Draft = 1, 
    Pending = 2, 
    Validated = 3, 
    Refused = 4 
} 

的想法是把List<ProjectVm>按照一定的順序,因此先通過有序1草稿,第二個由2待定,第三個由4由3驗證拒絕和第四位。

我當前的查詢看起來是這樣的:

projects = projects.OrderBy(x => x.StatusId).ToList(); 

不幸的是這查詢不尊重所需的順序(4配備3之前)。

你知道如何在這個查詢中應用一個條件來使項目進入正確的順序(1,2,4,3)嗎?

謝謝!

+0

x =>((Status)x.StatusId).ToString()) –

+0

@下面答案中的Compufreak的比較器實現是恕我直言,它是最好的,最可重用和最可持續的方式。 – JuanR

回答

1

只需使用幾個排序,第一個與OrderByDescending,那麼剩下的用ThenByDescending

projects = projects 
    .OrderByDescending(p => p.StatusId == Status.Draft) 
    .ThenByDescending(p => p.StatusId == Status.Pending) 
    .ThenByDescending(p => p.StatusId == Status.Refused) 
    .ThenByDescending(p => p.StatusId == Status.Validated) 
    .ToList(); 
-1

試試這個

var projectList= projects.OrderBy(x => (int)x.StatusId).ToList(); 
+1

這與沒有int轉換的情況完全相同。 – DavidG

1

這裏沒有一個乾淨的方式來做到這一點完全在線 - 你可以做類似的事情:

projects.OrderBy(x => x == Status.Validated ? int.MaxValue : (int)x.StatusId) 

強制驗證,以在年底,但我會寫一個函數:

private int CustomOrder(Status status) 
{ 
    switch(status) 
    { 
     // force Validated to the end 
     case Status.Validated: 
      return int.MaxValue; 
     default: 
      return (int)status; 
    } 
} 

,並從查詢調用它:

projects.OrderBy(x => CustomOrder(x)) 

既然你可以添加註釋和組織代碼,使它更清楚你的意圖是什麼。

另一種辦法是把值在數組中你想要的順序,然後才能通過他們的位置在數組中:

Status[] order = new [] {Draft, Pending, Refused, Validated}; 

projects.OrderBy(x => Array.IndexOf(order,x)); 
1

試試這個:

public static int MyCustomOrder (Status status) 
{ 
    switch (status) 
    { 
     case Status.Draft  : return 1; 
     case Status.Pending : return 2; 
     case Status.Validated : return 4; 
     case Status.Refused : return 3; 

     default: return -1; 
    } 
} 

現在:

var result = projects.OrderBy (x => MyCustomOrder (x.StatusId)); 
1

不是很漂亮,但應該工作:

projects.OrderBy(x => x.StatusId).ThenBy(c => c.StatusId == Status.Validated ? 1 : 0).ToList(); 

否則,您必須提供自己的Comparer:

class StatusComparer : IComparer<Status> 
     { 
      public int Compare(Status x, Status y) 
      { 
       if (x.Equals(y)) return 0; 
       return (x > y || x.Equals(Status.Validated)) ? 1 : -1; 
      } 
     } 

然後調用:

projects.OrderBy(x => x.StatusId, new StatusComparer()).ToList(); 

或者做一些喜歡這裏提出的其他人;)

1
projects.OrderBy(x => x.StatusId == Status.Validated).ThenBy(x => x.StatusId) 

在最後放置所有待處理的內容,然後使用StatusID在該規則內進行排序。兩個簡單的操作,並可能由任何提供商很好地處理。

projects.OrderBy(x => x.StatusId == Status.Validated ? int.MaxValue : (int)x.StatusId) 

的單個操作,這是因此有可能更快,此排序之前3Pending重新分配給int.MaxValue

我想嘗試第二個可能更有效的第一個,但第二個也值得注意作爲一般方法。

+0

您可能是指已驗證,而不是等待。 –

+0

@DanDumitru我做了,謝謝。 –