MVC3 网站。EF4.1 代码优先。
我将排序列和方向保存到会话,以便当用户返回页面时,网格仍保持相同的排序顺序。
我希望能够指定如何使用我保存的值对集合进行排序。
这。问题 = this.db.ITIssues.Orderby(this.sort + " " + this.sortdir)...
目前,我必须使用 switch 语句并处理字段 + 排序方向的每个不同组合。有没有更好的方法?
switch (this.Sort)
{
case "ITApplication.Name":
if (this.SortDir == "ASC")
this.Issues = this.db.ITIssues.OrderBy(i => i.ITApplication.Name).Where(i => i.ITAppGroupID == this.ITAppGroupID);
else
this.Issues = this.db.ITIssues.OrderByDescending(i => i.ITApplication.Name).Where(i => i.ITAppGroupID == this.ITAppGroupID);
break;
case "ITIssueType.Name":
if (this.SortDir == "ASC")
this.Issues = this.db.ITIssues.OrderBy(i => i.ITIssueType.Name).Where(i => i.ITAppGroupID == this.ITAppGroupID);
else
this.Issues = this.db.ITIssues.OrderByDescending(i => i.ITIssueType.Name).Where(i => i.ITAppGroupID == this.ITAppGroupID);
break;
case "CurrentStatus.Name":
if (this.SortDir == "ASC")
this.Issues = this.db.ITIssues.OrderBy(i => i.CurrentStatus.Name).Where(i => i.ITAppGroupID == this.ITAppGroupID);
else
this.Issues = this.db.ITIssues.OrderByDescending(i => i.CurrentStatus.Name).Where(i => i.ITAppGroupID == this.ITAppGroupID);
break;
case "CurrentAssignedTo.Fname":
if (this.SortDir == "ASC")
this.Issues = this.db.ITIssues.OrderBy(i => i.CurrentAssignedTo.Fname).Where(i => i.ITAppGroupID == this.ITAppGroupID);
else
this.Issues = this.db.ITIssues.OrderByDescending(i => i.CurrentAssignedTo.Fname).Where(i => i.ITAppGroupID == this.ITAppGroupID);
break;
case "CreatedBy.Fname":
if (this.SortDir == "ASC")
this.Issues = this.db.ITIssues.OrderBy(i => i.CreatedBy.Fname).Where(i => i.ITAppGroupID == this.ITAppGroupID);
else
this.Issues = this.db.ITIssues.OrderByDescending(i => i.CreatedBy.Fname).Where(i => i.ITAppGroupID == this.ITAppGroupID);
break;
case "CurrentPriority.Name":
if (this.SortDir == "ASC")
this.Issues = this.db.ITIssues.OrderBy(i => i.CurrentPriority.Name).Where(i => i.ITAppGroupID == this.ITAppGroupID);
else
this.Issues = this.db.ITIssues.OrderByDescending(i => i.CurrentPriority.Name).Where(i => i.ITAppGroupID == this.ITAppGroupID);
break;
default:
this.Issues = this.db.ITIssues.OrderByDescending(i => i.ID).Where(i => i.ITAppGroupID == this.ITAppGroupID);
break;
}
我最近不得不做类似的事情,你正在寻找的是动态 Linq!看看这个:
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
您的代码似乎有两个障碍,第一个涉及从 this.Sort
表示的字符串中获取属性名称。 这可能涉及一些反射代码。 第二部分涉及缩短指定升序排序与降序排序所需的代码量。
您可以通过多种方式做到这一点。 我想到的第一个想法是为 OrderBy 创建一个扩展方法,该方法采用布尔值 SortDir 参数。 OrderBy 有一些重载允许Func<T,TKey>
键选择器和IComparer<T>
。 我将向您展示仅使用keySelector的简单方法,但是您可能希望实现所有这些解决方案以获得完全通用的解决方案
public static class IEnumerableExtentions
{
public static IEnumerable<T> OrderBy<T,TKey>(this IEnumerable<T> source, Func<T, TKey> keySelector, bool reverse)
{
return reverse ? source.OrderByDescending(keySelector) : source.OrderBy(keySelector);
}
}
有了这个,你可以在没有所有这些if的情况下编写代码。
switch (this.Sort)
{
case "ITApplication.Name":
this.Issues = this.db.ITIssues.OrderBy(i => i.ITApplication.Name, this.SortDir == "ASC").Where(i => i.ITAppGroupID == this.ITAppGroupID);
break;
/*...*/
}
作为确定排序顺序的第二种解决方案,您传入一个使用 SortDir 的IComparer
。 这是您可以使用的 IComparer 实现
class ReversableComparer : IComparer<IComparable>
{
private bool _reverse;
public ReversableComparer(bool reverse)
{
_reverse = reverse;
}
public int Compare(IComparable x, IComparable y)
{
return _reverse ? y.CompareTo(x) : x.CompareTo(y);
}
}
然后你可以编写你的代码
switch (this.Sort)
{
case "ITApplication.Name":
this.Issues = this.db.ITIssues.OrderBy(i => i.ITApplication.Name, new ReversableComparer(this.SortDir != "ASC")).Where(i => i.ITAppGroupID == this.ITAppGroupID);
break;
/*...*/
}
这需要编写更多的代码,但如果您需要它,它就在那里。
就属性名称/反射而言,如果您使用 Linq 作为 Linq to SQL 的一部分,则 @AlbertVo 提供的动态 linq 链接可能值得一看。 如果您更多地使用 Linq to Objects,那么与其尝试使用 i => i.ITApplication.Name
i => i.GetType().GetProperty(this.Sort).GetValue(i, null)
当然,您需要System.Reflection
才能完成这项工作,并且它可能比原始解决方案慢。
我希望其中一些有所帮助。 干杯。
编辑总而言之,这两种技术可以结合起来。 最终代码可能如下所示:
public static class IEnumerableExtentions
{
public static IEnumerable<T> OrderBy<T,TKey>(this IEnumerable<T> source, Func<T, TKey> keySelector, bool reverse)
{
return reverse ? source.OrderByDescending(keySelector) : source.OrderBy(keySelector);
}
}
void Main()
{
this.Issues = this.db.ITIssues
.OrderBy(i => i.GetType().GetProperty(this.Sort).GetValue(i, null),
this.SortDir == "ASC")
.Where(i => i.ITAppGroupID == this.ITAppGroupID);
}