换了工作有一个月了,一样的工作、一样的代码、一样的体力活仍就……

Linq To Entityes 也是不新玩意了,近半年来也一直与之打交道,但一直也没对其深究过。今天新加的功能要对所有列支持排序,这也不是什么高难度的工作了,对与TSQL来说是写过几百遍了,但在Linq To Enitities中有点小恶心。

Linq To Entityes中的对象是个Queryable类型的,Queryable.OrderBy()方法的参数是一个Lamdba

source.OrderBy(t=>t.ID).Skip(0).Take(10)

表达式。第一个想到的便是用字段名反射出类型,如

source.OrderBy(t=>t.GetType().GetField(“ID”)).Skip(0).Take(10);

而运行时会报“无法识别GetField()方法”。

Linq实际上是一个表达式树,是基于语言级别的代码,OrderBy中需要一个表达式树。

在老外的网站上找到了如下代码,豁然开朗

        public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string property)
        { 
            return ApplyOrder<T>(source, property, "OrderBy"); 
        }
 
        public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> source, string property)
        { 
            return ApplyOrder<T>(source, property, "OrderByDescending"); 
        }
 
        public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, string property)
        {
            return ApplyOrder<T>(source, property, "ThenBy"); 
        }
 
        public static IOrderedQueryable<T> ThenByDescending<T>(this IOrderedQueryable<T> source, string property)
        { 
            return ApplyOrder<T>(source, property, "ThenByDescending"); 
        }
 
        static IOrderedQueryable<T> ApplyOrder<T>(IQueryable<T> source, string property, string methodName)
        {
            string[] props = property.Split('.');
            Type type = typeof(T); ParameterExpression arg = Expression.Parameter(type, "x");
            Expression expr = arg; foreach (string prop in props)
            { 
                // use reflection (not ComponentModel) to mirror LINQ 
                PropertyInfo pi = type.GetProperty(prop); expr = Expression.Property(expr, pi); type = pi.PropertyType;
            } 
            Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type); 
            LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg); 
            object result = typeof(Queryable).GetMethods().Single(method => method.Name == methodName 
                            && method.IsGenericMethodDefinition 
                            && method.GetGenericArguments().Length == 2 
                            && method.GetParameters().Length == 2)
                            .MakeGenericMethod(typeof(T), type)
                            .Invoke(null, new object[] { source, lambda }); 
            return (IOrderedQueryable<T>)result;
        }

上面的代码满足所有的排序功能了,我的项目中只需要对单列排序,所以对代码做了简化

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="property">排序字段</param>
        /// <param name="isAscdening"></param>
        /// <returns></returns>
        static IOrderedQueryable<T> ApplyOrder<T>(IQueryable<T> source, string property, bool isAscdening)
        {
            Type type = typeof(T);
            ParameterExpression arg = Expression.Parameter(type, "x");
            Expression expr = arg;
 
            PropertyInfo pi = type.GetProperty(property);
            expr = Expression.Property(expr, pi);
            type = pi.PropertyType;
 
            Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type);
            LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg);
 
            object result;
            if (true == isAscdening)
            {
                result = typeof(Queryable).GetMethods().
                    Single(method => method.Name == "OrderBy" && method.IsGenericMethodDefinition
                        && method.GetGenericArguments().Length == 2 && method.GetParameters().Length == 2).
                    MakeGenericMethod(typeof(T), type)
                    .Invoke(null, new object[] { source, lambda });
            }
            else
            {
                result = typeof(Queryable).GetMethods().
                    Single(method => method.Name == "OrderByDescending" && method.IsGenericMethodDefinition
                        && method.GetGenericArguments().Length == 2 && method.GetParameters().Length == 2).
                    MakeGenericMethod(typeof(T), type)
                    .Invoke(null, new object[] { source, lambda });
            }
            return (IOrderedQueryable<T>)result;
        } 

还可以将方法做Queryable的扩展方法,使用起来会更方便

根据列名动态生成查询


        static IQueryable<T> MakeQuery<T>(IQueryable<T> source, string colName, string colValue)
        { 
           Type theType = typeof(T);
            //创建一个参数c
            ParameterExpression param = Expression.Parameter(typeof(T), "c");
            //c.City=="London"
            Expression left = Expression.Property(param,typeof(T).GetProperty(colName));
            Expression right = Expression.Constant(colValue);
            Expression filter = Expression.Equal(left, right);             Expression pred = Expression.Lambda(filter, param);
            //Where(c=>c.City=="London")
            Expression expr = Expression.Call(typeof(Queryable), "Where",
                new Type[] { typeof(T) }, 
                Expression.Constant(source), pred);
            //生成动态查询
            IQueryable<T> query = source.AsQueryable()
                .Provider.CreateQuery<T>(expr);
            return query;
        }
 

Linq To Entities中的动态排序的更多相关文章

  1. LINQ to Entities 中的查询

    MSDN地址:https://msdn.microsoft.com/zh-cn/library/bb399367%28v=vs.100%29.aspx .NET Framework 4 查询是一种从数 ...

  2. LINQ中的动态排序

    使用Linq动态属性排序 使用反射: public static Func<T,Tkey> DynamicLambda<T, Tkey>(string propertyName ...

  3. .net mvc datatables中orderby动态排序

    今天在做项目中用datatables的排序来做筛选,不过人比较懒,不想写那么多的关于排序的代码,于是寻思这在度娘上找找,结果不负有心人啊,更感谢贴出此贴的哥们,来源:http://blog.csdn. ...

  4. Linq to Entities中无法构造实体或复杂类型

    EF中在使用linq就行查询select时不能直接使用自动映射生成的类,需要在单独声明一个类或者使用匿名类在查询完成后再转为对应的对象. public partial class WebForm1 : ...

  5. 在linq to entities中无法使用自定义方法

    来源: http://support.microsoft.com/kb/2588635/zh-tw (繁体)

  6. LINQ to Entities 查询中的标准查询运算符

    投影和筛选方法 投影指的是转换的结果集到所需的窗体中的元素. 例如,可以从结果集中的每个对象投影所需的属性子集,可以投影一个属性并对其执行数学计算,也可以从结果集投影整个对象. 投影方法有 Selec ...

  7. Linq To Entities 及其相关(进阶)

    上篇我们讲解了Linq To Entities的一些基本操作,这篇我们主要是讲解一些比较高级的东西:存储过程查询,SQL语句查询以及表达式树. 存储过程 首先来讲解存储过程查询. //Query a ...

  8. LINQ to Entities不识别方法***,因此该方法无法转换为存储表达式

    我的程序里有这么一段代码: order.OrderExpressInfo = (from oei in orderExpressRepository.Entities where oei.OrderI ...

  9. linq扩展之动态排序

    前两天看QQ群里面,一位朋友问的问题,说在linq中怎么实现动态排序呢,自己想了半天,没有头绪,网上找了下相关的资料,看了下,收益挺多,记录下来. 之前我们没有如果不知道动态排序的方法的话,我们可能会 ...

随机推荐

  1. SpringCloud版本介绍和SpringBoot的兼容性

    Spring Cloud是一个由众多独立子项目组成的大型综合项目,每个子项目有不同的发行节奏,都维护着自己的发布版本号.Spring Cloud通过一个资源清单BOM(Bill of Material ...

  2. Firefox--摄像头麦克风权限

    在自动化测试的过程中,可能会遇到来自浏览器的权限提示(摄像头.麦克风),今天,就讨论一下如何结局这个问题. 先来认识一下来自Firefox的权限提示,访问一个需要摄像头或者麦克风的网站 你可能觉得,一 ...

  3. virsh 命令

    virsh是用与管理虚拟化环境中的客户机和Hypervisor的命令行工具,与virt-manager等工具类似,也是调用libvirt API来实现虚拟化的管理. 在使用virsh命令行进行虚拟化管 ...

  4. Android开发——使用ADB Shell命令实现模拟点击(支付宝自动转账实现)

    首先声明,本人反对一切利用技术的违法行为 本文的实现代码已经销毁,本文以介绍流程为主 1.这里所说的模拟点击不是在自己的APP里点击,点自己APP上的控件没什么好说的 不仅是支付宝转账,其他的获取别人 ...

  5. 大数据学习——点击流日志每天都10T,在业务应用服务器上,需要准实时上传至(Hadoop HDFS)上

    点击流日志每天都10T,在业务应用服务器上,需要准实时上传至(Hadoop HDFS)上 1需求说明 点击流日志每天都10T,在业务应用服务器上,需要准实时上传至(Hadoop HDFS)上 2需求分 ...

  6. jmeter-添加断言(检查点)-实例

    方法/步骤     打开 jmeter的图形界面工具,然后打开之前保存的脚本(之前经验中用到的),demo-baidu.jmx   先点击运行,查看运行结果. 第一次请求返回302,然后跳转到第二次请 ...

  7. oracle等待事件相关查询

    --------------------------查询数据库等待时间和实际执行时间的相对百分比--------------------- select *   from v$sysmetric a ...

  8. [BZOJ3052][UOJ#58][WC2013]糖果公园

    [BZOJ3052][UOJ#58][WC2013]糖果公园 试题描述 Candyland 有一座糖果公园,公园里不仅有美丽的风景.好玩的游乐项目,还有许多免费糖果的发放点,这引来了许多贪吃的小朋友来 ...

  9. HDU 3932 模拟退火

    HDU3932 题目大意:给定一堆点,找到一个点的位置使这个点到所有点中的最大距离最小 简单的模拟退火即可 #include <iostream> #include <cstdio& ...

  10. CSU 1307 最短路+二分

    题目大意: 帮忙找到一条a到b的最短路,前提是要保证路上经过的站点的最大距离尽可能短 这道题居然要用到二分...完全没去想过,现在想想求最大距离的最小值确实是... 这里不断二分出值代入spfa()或 ...