Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用文本值而不是lambda进行Linq排序_Linq_Sorting - Fatal编程技术网

使用文本值而不是lambda进行Linq排序

使用文本值而不是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

MVC3网站。EF4.1代码优先

我正在将排序列和方向保存到会话中,这样当用户返回页面时,网格仍处于相同的排序顺序

我希望能够指定如何使用保存的值对集合进行排序

this.Issues=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!看看这个:


最近我不得不做一些类似的事情,你要找的是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