前面介绍了Linq的三个方面应用:Linq to SQL, Linq to XML和Linq to Object,这篇介绍一下动态Linq的实现方式及应用场景。

命名空间:

System.Linq;

System.Linq.Expressions;

应用Linq的时候,我们都知道仅仅须要Lambda表达式即可,但有些场景仅仅仅仅使用Data Model的字段名操作是不够的或者不方便的。

场景1:如果我们须要拼接Where条件进行查询,一种方式能够拼接IQueryable的表达式。但我想像写SQL语句那样直接拼接一个Where条件即可,Linq要怎么实现?

场景2:如果我们想要一个列表,这个列表能够按每一个表头来排序,我们把表头当作參数传给排序函数,在函数内部该怎么实现呢?能够逐一枚举对照,针对不同的列写不同的Linq语句,但代码非常冗余。用传统方式依据动态字段名怎么实现?

以下来说说Linq的还有一种应用方式: 动态Linq,使用Linq.Expressions. 场景1, 我仅仅想用Where拼接(表名參数)就完毕操作,以下看看实现。以下全部的Demo仅仅是应用于Linq to SQL, 假设是Entity Framework会有差异.

DataClasses1DataContext dbContext = new DataClasses1DataContext();

public string dynamicLinq(int id = 50)

        {

            IQueryable<DataListForDemo> dLinq = dbContext.DataListForDemos;

ParameterExpression paraExpr = Expression.Parameter(typeof(DataListForDemo), "data");

            MemberExpression propExpr = Expression.Property(paraExpr, typeof(DataListForDemo).GetProperty("ID"));

            BinaryExpression filter = Expression.LessThan(propExpr, Expression.Constant(id));

            LambdaExpression lambdaWhere = Expression.Lambda(filter, paraExpr);

MethodCallExpression Where = Expression.Call(typeof(Queryable),

                                                                "Where",

                                                                new Type[] { typeof(DataListForDemo) },

                                                                Expression.Constant(dLinq),

                                                                lambdaWhere

                                                            );

var data0 = dLinq.AsQueryable().Provider.CreateQuery(Where);

DbCommand comm = dbContext.GetCommand(data0);

            dbContext.Log(comm.CommandText);

return comm.CommandText;

        }

上面是各种Linq.Expression的类, 用ParameterExpression定义參数也就是要操作的实体对象, 用PropertyExpression定义属性也就是要操作的字段, 用BinaryExpression定义条件查询的表达式也就是Where条件, 用LambdaExpression定义Lambda表达式也就是IQueryable对象, 最后一步就是来完毕调用. Call方法是来定义你的表达式方法, 如: Where, Select, OrderBy, GroupBy, All, Any,
Equal等等方法, 有哪一种动态需求就写哪一种方法, 这个在MSDN上面没有太多实例, 只是网上能够查到非常多.

上面返回的是生成的SQL语句, SQL语句是这种:

SELECT [t0].[ID], [t0].[col1], [t0].[col2], [t0].[col3], [t0].[col5], [t0].[col4]

FROM [dbo].[DataListForDemo] AS [t0]

WHERE [t0].[ID] < @p0

对比生成的SQL语句和Expression的表达式就非常easy理解Linq是怎么实现的和怎么工作的. 那么有些人会问, IQueayable和IEnuerable的对象都会带有Linq的表达式而并非单独的方法通过传參数实现, 要实现这样的方式那么就得提一下什么是扩展方法以及扩展方法怎么实现. 在C#里面要扩展某个对象的方法能够override基类方法, 可是像string, iqueryable等这样的对象怎么扩展它们的方法呢? Override基类当然不行, 这时就要用thiskeyword,也是this的还有一种应用方式.

使用扩展方法, 首先写一个静态类, 在静态类里面定义一个静态方法, 静态方法里面第一个參数以this開始, 第一个參数也就是你要扩展的系统对象.

如:

public static class DynamicQueryable

{

//扩展IQueryable对象的方法

public static IQueryable Where(this IQueryable source, string predicate, params object[] values)

        {

            if (source == null) throw new ArgumentNullException("source");

            if (predicate == null) throw new ArgumentNullException("predicate");

            LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, typeof(bool), predicate, values);

            return source.Provider.CreateQuery(

                Expression.Call(

                    typeof(Queryable), "Where",

                    new Type[] { source.ElementType },

                    source.Expression, Expression.Quote(lambda)));

        }

public static LambdaExpression ParseLambda(Type itType, Type resultType, string expression, params object[] values)

        {

            return ParseLambda(new ParameterExpression[] { Expression.Parameter(itType, "") }, resultType, expression, values);

        }

}

上面就是扩展IQueryabler方法, 所以IQueryable类型的全部对象都有了动态Where的功能, 我不知道为什么Microsoft团队没有把这个功能加上, 而仅仅是提供了Expressions类, 加上这些动态表达之后Linq功能会很强壮.

来看看调用:

public string SelectDynamic(int id = 0)

        {

            DataListForDemo model = dbContext.DataListForDemos.Where("ID = " + id.ToString()).SingleOrDefault();

            return model.ID.ToString();

        }

如今非常明显的一个变化是Where里面能够仅仅写一个拼接的where条件了, 并且是一个字符串, 这就是大多数程序猿想到的东东吧!

Linq里面全部已经存在的方法都能够通过这样的方式扩展和实现动态化, 很多其它的实现方式能够Google, 建议使用Google, 英文文章有的写得很透彻,并且资源丰富.




Linq技术四:动态Linq技术 -- Linq.Expressions的更多相关文章

  1. 代理模式 & Java原生动态代理技术 & CGLib动态代理技术

    第一部分.代理模式  代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常 ...

  2. Java基础---Java---基础加强---类加载器、委托机制、AOP、 动态代理技术、让动态生成的类成为目标类的代理、实现Spring可配置的AOP框架

    类加载器 Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader,AppClassLoader 类加载器也是Jav ...

  3. 插件化开发—动态载入技术载入已安装和未安装的apk

    首先引入一个概念,动态载入技术是什么?为什么要引入动态载入?它有什么优点呢?首先要明确这几个问题.我们先从 应用程序入手,大家都知道在Android App中.一个应用程序dex文件的方法数最大不能超 ...

  4. 【转】Entity Framework技术系列之7:LINQ to Entities

    前言 LINQ(Language Integrated Query,语言集成查询)是一组用于C#和VB.NET语言的扩展,它允许编写C#或者VB.NET代码,以与查询数据库相同的方式操作内存数据. L ...

  5. [LINQ2Dapper]最完整Dapper To Linq框架(四)---Linq和SQL并行使用

    目录 [LINQ2Dapper]最完整Dapper To Linq框架(一)---基础查询 [LINQ2Dapper]最完整Dapper To Linq框架(二)---动态化查询 [LINQ2Dapp ...

  6. Linq to Sql : 动态构造Expression进行动态查询

    原文:Linq to Sql : 动态构造Expression进行动态查询 前一篇在介绍动态查询时,提到一个问题:如何根据用户的输入条件,动态构造这个过滤条件表达式呢?Expression<Fu ...

  7. [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程

    [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程 本节导读:本节主要介绍什么是.NET反射特性,.NET反射能为我们做些什么,最后介绍几种常用的 ...

  8. iOS中 动态热修补技术JSPatch 韩俊强的博客

    .1.4) JSPatch bridge Objective-C and JavaScript. You can call any Objective-C class and method in Ja ...

  9. 动态页面技术JSP/EL/JSTL

    本节内容: jsp脚本和注释 jsp运行原理 jsp指令(3个) jsp内置/隐式对象(9个) jsp标签(动作) EL技术 JSTL技术 JavaEE的开发模式 动态页面技术:就是在html中嵌入j ...

随机推荐

  1. all about AIX MPIO

    Multipath  I/O (多路径)   在计算机存储技术里,多路径提供了容错和性能提高,在计算机系统里CPU有多条物理路径通道,块存储设备通过总线,控制器,交换设备以及桥接设备来连接.     ...

  2. LVM 命令集总结(转)

    PV 命令 下面的命令是在与物理卷相关的操作中最常用的命令: lsdev 列出ODM中的设备. chdev 修改设备的特征. mkdev 增加一个设备到系统中. chpv 修改物理卷的状态. lspv ...

  3. ehcache历史变迁及常用API的使用(转)

    ehcache是一个用Java实现的使用简单,高速,实现线程安全的缓存管理类库,ehcache提供了用内存,磁盘文件存储,以及分布式存储方式等多种灵活的cache管理方案.同时ehcache作为开放源 ...

  4. UVa 10012 - How Big Is It? 堆球问题 全排列+坐标模拟 数据

    题意:给出几个圆的半径,贴着底下排放在一个长方形里面,求出如何摆放能使长方形底下长度最短. 由于球的个数不会超过8, 所以用全排列一个一个计算底下的长度,然后记录最短就行了. 全排列用next_per ...

  5. poj 1004 Dividing

    大意是,从输入六个数 .第i个数代表价值为i的有几个,平均分给两个人 ,明摆着的背包问题,本来以为把他转化为01背包.可是TLe,后来发现是12万的平方还多,所以妥妥的TLE,后来发现这是一个全然背包 ...

  6. python 基础知识点整理 和详细应用

    Python教程 Python是一种简单易学,功能强大的编程语言.它包含了高效的高级数据结构和简单而有效的方法,面向对象编程.Python优雅的语法,动态类型,以及它天然的解释能力,使其成为理想的语言 ...

  7. (2)虚拟机下hadoop1.1.2集群环境搭建

    hadoop集群环境的搭建和单机版的搭建差点儿相同,就是多了一些文件的配置操作. 一.3台主机的hostname改动和IP地址绑定 注意:以下的操作我都是使用root权限进行! (1)3太主机的基本网 ...

  8. mvc5 解析route源码实现自己的route系统

    Asp.net mvc5 解析route源码实现自己的route系统   url route 路由系统的责任是找到匹配的路由,创建路由数据,并将请求分配给一个处理程序. 选择动作是 MVC 的处理程序 ...

  9. RSA JS 加密解密DEMO

    <script src="Scripts/jquery-1.4.1.js" type="text/javascript"></script&g ...

  10. android账号与同步之发起同步

    上一篇博文我介绍了账号与同步的同步实现过程,当中提供了一个工系统进程调用的服务,那么这个服务究竟是怎么被启动和使用的呢?这篇博文我就大体梳理一下启动过程. 事实上作为一个一般开发者,我们仅仅要知道要想 ...