前面介绍了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的表达式就很容易理解Linq是怎么实现的和怎么工作的. 那么有些人会问, IQueayable和IEnuerable的对象都会带有Linq的表达式而并不是单独的方法通过传参数实现, 要实现这种方式那么就得提一下什么是扩展方法以及扩展方法怎么实现. 在C#里面要扩展某个对象的方法可以override基类方法, 但是像string, iqueryable等这种对象怎么扩展它们的方法呢? Override基类当然不行, 这时就要用this关键字,也是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. linux密码安全加固技术-CKEY动态密码技术【顶】

    基于动态令牌的双因素身份认证--有力保障网上帐户和交易的安全  一. 网络安全认证的需求背景      网络钓鱼.欺诈等网络犯罪现象已经达到非常严峻的情况,用户如果只依赖个人密码进行帐户登录或网上交易 ...

  2. ASP PHP和JSP三大动态网页技术

    ASP.PHP.JSP三者都是面向Web服务器的技术,客户端浏览器不需要任何附加的软件支持.程序代码的执行结果被重新嵌入到HTML代码中,然后一起发送给浏览器.在ASP.PHP.JSP环境下,HTML ...

  3. 【LINQ技术】扩展特性和LINQ操作符

    LINQ特有的编程结构 LINQ就像是嵌入到C#中的强类型查询语言,尽管和SQL查询很像,但语法却并不相同,甚至还有截然相反的一面. LINQ是在.NET发展到3.5版的时候被引进的,C#和VB语言都 ...

  4. QueryBuilder : 打造优雅的Linq To SQL动态查询

    首先我们来看看日常比较典型的一种查询Form 这个场景很简单:就是根据客户名.订单日期.负责人来作筛选条件,然后找出符合要求的订单. 在那遥远的时代,可能避免不了要写这样的简单接口: public i ...

  5. Linq 通过反射动态查询对象

    public IQueryable<TEntity> Find<TEntity>(TEntity obj) where TEntity : class         {    ...

  6. LINQ篇:ASP.NET using LINQ(Part One) Scott大师的产物

    [原文地址]Using LINQ with ASP.NET (Part 1) [原文发表日期]Sunday, May 14, 2006 9:49 PM 最近使我激动不已的新鲜事之一就是LINQ系列技术 ...

  7. 动态缩略图技术实现思路

    原文:http://www.cnblogs.com/schwann/archive/2014/04/28/3698172.html 在网站开发过程中,大家都是如何解决多尺寸图片缩略图问题的呢?犹为典型 ...

  8. 30~60万|项目需求——胳膊与手指的动态识别技术

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 项目需求:胳膊与手指的动态识别技术 需求内容:机器无法通过语言解读人的具体指令,可通过具体的手势来完成 ...

  9. 配置单臂路由、三层交换技术以及动态路由

    实验05:配置单臂路由 一. 实验目标 通过Cisco Packet Tracer来配置单臂路由. 二.实验环境和拓扑 window 7操作系统,Cisco Packet Tracer软件. 拓扑结构 ...

最新文章

  1. 如何高效的利用博客园?
  2. Linux内存管理 (4)分配物理页面
  3. 演示FileInputStream案例演示
  4. LeetCode 35. 搜索插入位置(二分查找)
  5. 一年发表603篇论文、研究被引近3.9万次,学者操纵引文遭质疑
  6. selenium-js
  7. 《Java编程思想》读后感
  8. 世界上最好玩的6种表情符号编程语言
  9. 《仿人机器人原理与实战》一第1章
  10. WiFi 5G频段差分巴伦电路对接收灵敏度的影响
  11. 【BZOJ1492】【NOI2007】货币兑换 Cash(CDQ分治,斜率优化)
  12. Unity 使用AVProVideo插件加载并下载视频
  13. 计算机二级考试报名如何上传照片?
  14. 开课吧 python与人工智能 下载_开课吧app|开课吧手机版下载v2.3.6安卓版 - 欧普软件下载...
  15. LOD(Levels of detail)细节层次3D优化
  16. 跟风用Matlab画一棵圣诞树
  17. 红帽6虚拟机安装流程
  18. Unity 工具之 获取当前所在城市的天气数据的封装(自动定位当前所在城市,天气数据可以获得多天天数据)
  19. 陪诊服务系统源码,可以在线预约陪诊师的软件平台
  20. DotCMS中文教程

热门文章

  1. 修改服务器端数据库,问道1.6 开区 服务器环境配置 数据库修改 服务端启动教程...
  2. Proxifier Socks5 代理(内网访问、远程办公)
  3. tomcat配置监控界面
  4. android 取消系统默认手机加密(全盘加密)
  5. 音频编码之opus(一)
  6. 2021年煤矿安全监测监控新版试题及煤矿安全监测监控
  7. 定义一个复数类Complex,重载运算符“+”,“ -”,“*”,“/”使之能用于计算两个复数的加减乘除。
  8. Android 10 SSL双向认证握手失败
  9. [ FI基本业务流程 ] - FI与MM间的业务集成
  10. 07 ,日志入库项目 :