2017-07-07 66 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我做了,谢谢。 –