使用文本值而不是lambda进行Linq排序
MVC3网站。EF4.1代码优先 我正在将排序列和方向保存到会话中,这样当用户返回页面时,网格仍处于相同的排序顺序 我希望能够指定如何使用保存的值对集合进行排序 this.Issues=this.db.ITIssues.Orderby(this.sort+“”+this.sortdir) 目前,我必须使用switch语句并处理字段和排序方向的每个不同组合。 有更好的办法吗使用文本值而不是lambda进行Linq排序,linq,sorting,Linq,Sorting,MVC3网站。EF4.1代码优先 我正在将排序列和方向保存到会话中,这样当用户返回页面时,网格仍处于相同的排序顺序 我希望能够指定如何使用保存的值对集合进行排序 this.Issues=this.db.ITIssues.Orderby(this.sort+“”+this.sortdir) 目前,我必须使用switch语句并处理字段和排序方向的每个不同组合。 有更好的办法吗 switch (this.Sort) { case "ITApplication.Name": if
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!看看这个:
最近我不得不做一些类似的事情,你要找的是Dynamic Linq!看看这个:
代码中似乎有两个障碍,第一个障碍是从this.Sort所表示的字符串中获取属性名。这可能会涉及一些反射代码。第二部分涉及缩短指定升序排序与降序排序所需的代码量 你可以用几种方法来做这件事。我想到的第一个想法是为OrderBy创建一个扩展方法,它接受bool-SortDir参数。OrderBy有一些重载,允许使用
Func
键选择器和IComparaer
。我将向您展示一个只包含一个键选择器的简单解决方案,但您可能希望为一个完全通用的解决方案实现所有这些解决方案
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);
}
}
作为确定排序顺序的第二种解决方案,您传入一个使用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);
}
}
这需要编写更多的代码,但如果您需要,它就在那里
就属性名称/反射而言,如果您使用Linq作为LINQtoSQL的一部分,那么@AlbertVo提供的动态Linq链接可能值得一看。如果您更多地使用Linq to对象,那么不要使用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);
}
公共静态类IEnumerableExtensions
{
公共静态IEnumerable OrderBy(此IEnumerable源、Func键选择器、布尔反向)
{
返回反向?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”)
其中(i=>i.ITAppGroupID==this.ITAppGroupID);
}
代码中似乎有两个障碍,第一个障碍是从this.Sort所表示的字符串中获取属性名。这可能会涉及一些反射代码。第二部分涉及缩短指定升序排序与降序排序所需的代码量
你可以用几种方法来做这件事。我想到的第一个想法是为OrderBy创建一个扩展方法,它接受bool-SortDir参数。OrderBy有一些重载,允许使用Func
键选择器和IComparaer
。我将向您展示一个只包含一个键选择器的简单解决方案,但您可能希望为一个完全通用的解决方案实现所有这些解决方案
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);
}
}
作为确定排序顺序的第二种解决方案,您传入一个使用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);
}
}
这需要编写更多的代码,但如果您需要,它就在那里
就属性名称/反射而言,如果您使用Linq作为LINQtoSQL的一部分,那么@AlbertVo提供的动态Linq链接可能值得一看。如果您更多地使用Linq to对象,那么不要使用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);
}
公共静态类IEnumerableExtensions
{
公共静态IEnumerable OrderBy(此IEnumerable源、Func键选择器、布尔反向)
{
返回反向?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”)
其中(i=>i.ITAppGroupID==this.ITAppGroupID);
}
我昨天在看那篇文章。我希望不必求助于另一个图书馆,也许我在林克错过了什么。谢谢你的帖子。我昨天在看那篇帖子。我希望不必求助于另一个图书馆,也许我在林克错过了什么。谢谢你的帖子。马丁,谢谢你的建议和代码。我发现很难相信每个人都在使用switch语句来排序他们的动态排序顺序。好像。。。我不知道linq是如何在幕后工作的,所以写了一个“看起来像”。我会等待更多的评论,如果没有更多的评论,我会将此标记为答案。再次感谢。@TPSpencer我还注意到,在所有情况下,.Where(…)部分都是相同的。因为Linq是可组合的,所以您可以从您提供的代码段中删除所有.Where子句,并在切换之后放置一个额外的赋值。类似于this.Issues=this.Issues.Where(…)
好的观点马丁,谢谢你指出这一点。最后的代码编辑看起来像promis