为linq到实体创建动态排序方法

时间:2011-05-20 22:56:11

标签: c# linq entity-framework lambda linq-expressions

  

可能重复:
  Dynamic LINQ OrderBy

我正在使用Entity Framework,并希望创建自己的动态排序方法,让您输入一个字符串来进行排序,例如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);
    }
}

非常感谢。

0 个答案:

没有答案