2

可能重复:
动态 LINQ OrderBy

我正在使用实体框架并想创建自己的动态排序方法,让您输入一个字符串来进行排序,例如query.DynamicSort("Name, Age DESC").

我知道 MS 已经发布了一些动态 linq 代码,但这超出了我的需要,我正在尝试了解如何自己编写一个简化版本来进行排序。

我有一些运气让它适用于单个字段......但是当我尝试按多个字段排序时,我收到以下错误:

参数“x”未绑定在指定的 LINQ to Entities 查询表达式中。

这是我的代码。任何人都可以看到我哪里出错并可能提出一些修改吗?我在动态构造表达式方面很弱。

public static class DynamicQuery
{
    private class SortField
    {
        public Expression Expression;
        public bool       Descending = false;
        public Type       Type;
    }

    public static IOrderedQueryable<T> DynamicSort<T>(this IQueryable<T> source, string sortOrder)
    {
        var fields     = sortOrder.Split(',');
        var sortFields = new List<SortField>();

        ParameterExpression arg = null;

        for (int i = 0; i < fields.Length; i++)
        {
            var sf = new SortField();
            sortFields.Add(sf);

            //Handle Descending Sort Fields
            if (fields[i].EndsWith(" DESC", StringComparison.OrdinalIgnoreCase))
            {
                sf.Descending = true;
                fields[i] = fields[i].Substring(0, (fields[i].Length - 5));  //Remove " DESC"
            }

            fields[i] = fields[i].Trim();

            //Handle fields that have nested properties
            var props = fields[i].Split('.');
            sf.Type = typeof(T);
            sf.Expression = arg = Expression.Parameter(sf.Type, "x");  //Create an x parameter of type T

            foreach (string prop in props)
            {
                PropertyInfo pi = sf.Type.GetProperty(prop);
                sf.Expression = Expression.Property(sf.Expression, pi);
                sf.Type = pi.PropertyType;
            }
        }

        //Now that we have the SortFields we can do the sorting
        Expression queryExpr = source.Expression;
        string methodAsc = "OrderBy";
        string methodDesc = "OrderByDescending";
        foreach (var sf in sortFields)
        {
            LambdaExpression lambda = Expression.Lambda(sf.Expression, arg);

            queryExpr = Expression.Call(
                typeof(Queryable), sf.Descending ? methodDesc : methodAsc,
                new Type[] { source.ElementType, sf.Type },
                queryExpr, Expression.Quote(lambda));
            methodAsc = "ThenBy";
            methodDesc = "ThenByDescending";
        }
        return (IOrderedQueryable<T>)source.Provider.CreateQuery(queryExpr);
    }
}

非常感谢。

4

0 回答 0