表达式树ExpressionTree
表达式树基础
考虑下面简单的Lambda表达式:
- 一个声明: Func<int, int, int> function
- 一个等号: =
- 一个lambda表达式: (a,b) => a + b;
变量function指向两个数字相加的原生可执行代码。上面三步的lambda表达式表示一个简短的如下的手写方法:
上面的方法或lambda表达式都可以这样调用:
当方法调用后,变量c将被设成3+5,即8。
上面声明中第一步委托类型Func是在System命名空间中为我们定义好的:
现在我们可以创建一个表达式树:
图1:VS2008 C# Samples中的ExpressionTreeVisualizer创建一个表达式树的象征性的输出
- Body: 得到表达式的主体。
- Parameters: 得到lambda表达式的参数.
- NodeType: 获取树的节点的ExpressionType。共45种不同值,包含所有表达式节点各种可能的类型,例如返回常量,例如返回参数,例如取两个值的小值(<),例如取两个值的大值(>),例如将值相加(+),等等。
- Type: 获取表达式的一个静态类型。在这个例子里,表达式的类型是Func<int, int, int>。
这段代码产生如下输入:
(a + b)
表达式左边部分: a
节点类型: Add
表达式右边部分: b
类型: System.Int32
同样,你会发现很容易在图1的Body节点中找到这些信息。
为什么要将LINQ to SQL查询表达式转换成表达式树呢?
你已经学习了表达式树是一个用来表示可执行代码的数据结构。但到目前为止我们还没有回答一个核心问题,那就是为什么我们要做这样的转换。这个问题是我们在本文开始时提出来的,现在是时候回答了。
一个LINQ to SQL查询不是在你的C#程序里执行的。相反,它被转换成SQL,通过网络发送,最后在数据库服务器上执行。换句话说,下面的代码实际上从来不会在你的程序里执行:
var query = from c in db.Customers
where c.City == "Nantes"
select new { c.City, c.CompanyName };
它首先被转换成下面的SQL语句然后在服务器上执行:
SELECT [t0].[City], [t0].[CompanyName]
从查询表达式的代码转换成SQL查询语句----它可以通过字符串形式被发送到其他程序。在这里,这个程序恰好是SQL Server数据库。像这样将数据结构转换到SQL显然比直接从原生IL或可执行代码转换到SQL要容易得多。这有些夸大问题的难度,只要试想转换0和1的序列到SQL!
现在是时候将你的查询表达式转换成SQL了,描述查询的表达式树是分解并解析了的,就像我们在上一节分解我们的简单的lambda表达式树一样。当然,解析LINQ to SQL表达式树的算法比我们用的那个要复杂得多,但规则是一样的。一旦解析了表达式树的各部分,那么LINQ开始斟酌以最好的方式生成返回被请求的数据的SQL语句。
表达式树被创建是为了制造一个像将查询表达式转换成字符串以传递给其他程序并在那里执行这样的转换任务。就是这么简单。没有巨大奥秘,不需要挥舞魔杖。只是简单的:把代码,转换成数据,然后分析数据发现其组成部分,最后转换成可以传递到其他程序的字符串。
由于查询来自编译器封装的抽象的数据结构,编译器可以获取任何它想要的信息。它不要求执行查询要在特定的顺序,或用特定的方式。相反,它可以分析表达式树,寻找你要做的是什么,然后再决定怎么去做。至少在理论上,我们可以自由的考虑各种因素,比如网络状况,数据库负载,结果集是否有效,等等。在实际中LINQ to SQL不考虑所有这些因素,但它理论上可以自由的做几乎所有想做的事。此外,人们可以通过表达式树将自己编写的代码,分析并转换成跟LINQ to SQL提供的完全不同的东西。
- 如果代码可以在程序里执行那么可以使用名为IEnumerable<T>的简单类型完成任务
- 如果你需要将查询表达式转换成将传递到其他程序的字符串,那么应该使用IQueryable<T>和表达式树。
var query = from method in typeof(System.Linq.Enumerable).GetMethods()
orderby method.Name
group method by method.Name into g
select new { Name = g.Key, Overloads = g.Count() };
概要
本文覆盖了表达式树的一些基本情况。通过将代码转换成数据,这些数据结构揭示并描绘表达式的组成部分。从最小的概念上讲,理解表达式树是相当简单的。它获取可执行表达式并获取其组成部分放入树形数据结构。例如,我们检测这个简单的表达式:
(a,b) => a + b;
通过研究来源于这个表达式的树,你能看到创建树的基本规则,见图1。
你同样可以看到表达式树在LINQ to SQL里扮演非常重要的角色。尤其,他们是LINQ to SQL查询表达式用来获取逻辑的数据抽象。解析并分析此数据得到SQL语句,然后发送到服务器。
LINQ使查询C#语言的一个普通类即有类型检查也有智能感知。其代码是类型检查和智能感知的,必须使用正确的C#语法,它能直接转换到可执行代码,就像任何其他C#代码一样被转换和执行。表达式树使将可执行代码转换成能传递到服务器的SQL语句相对容易。
查询返回IEnumerable<T>优于IQueryable<T>表示不使用表达式树。作为一般性规则,可以这么说:LINQ查询在程序内执行时不需要表达式树,当代码在程序外执行时可以利用表达式树。
表达式树ExpressionTree的更多相关文章
- C#特性-表达式树
表达式树ExpressionTree 表达式树基础 转载需注明出处:http://www.cnblogs.com/tianfan/ 刚接触LINQ的人往往觉得表达式树很不容易理解.通过这篇文章我希 ...
- IEnumerable和IQueryable的区别以及背后的ExpressionTree表达式树
关于IEnumerable和IQueryable的区别,这事还要从泛型委托Func<T>说起.来看一个简单的泛型委托例子: class Program { static void Main ...
- [.net 面向对象程序设计进阶] (7) Lamda表达式(三) 表达式树高级应用
[.net 面向对象程序设计进阶] (7) Lamda表达式(三) 表达式树高级应用 本节导读:讨论了表达式树的定义和解析之后,我们知道了表达式树就是并非可执行代码,而是将表达式对象化后的数据结构.是 ...
- 程序猿修仙之路--数据结构之你是否真的懂数组? c#socket TCP同步网络通信 用lambda表达式树替代反射 ASP.NET MVC如何做一个简单的非法登录拦截
程序猿修仙之路--数据结构之你是否真的懂数组? 数据结构 但凡IT江湖侠士,算法与数据结构为必修之课.早有前辈已经明确指出:程序=算法+数据结构 .要想在之后的江湖历练中通关,数据结构必不可少. ...
- 用lambda表达式树替代反射
本节重点不讲反射机制,而是讲lambda表达式树来替代反射中常用的获取属性和方法,来达到相同的效果但却比反射高效. 每个人都知道,用反射调用一个方法或者对属性执行SetValue和GetValue操作 ...
- Python与数据结构[3] -> 树/Tree[1] -> 表达式树和查找树的 Python 实现
表达式树和查找树的 Python 实现 目录 二叉表达式树 二叉查找树 1 二叉表达式树 表达式树是二叉树的一种应用,其树叶是常数或变量,而节点为操作符,构建表达式树的过程与后缀表达式的计算类似,只不 ...
- Linq系列(7)——表达式树之ExpressionVisitor
大家好,由于今天项目升级,大家都在获最新代码,所以我又有时间在这里写点东西,跟大家分享. 在上一篇的文章中我介绍了一个dll,使大家在debug的时候可以可视化的看到ExpressionTree的Bo ...
- 【C++】朝花夕拾——表达式树
表达式树: 叶子是操作数,其余结点为操作符,是二叉树的其中一种应用 ====================我是分割线====================== 一棵表达式树如下图: 若是对它做中序 ...
- 再讲IQueryable<T>,揭开表达式树的神秘面纱
接上篇<先说IEnumerable,我们每天用的foreach你真的懂它吗?> 最近园子里定制自己的orm那是一个风生水起,感觉不整个自己的orm都不好意思继续混博客园了(开个玩笑).那么 ...
随机推荐
- windows下eclipse搭建android_ndk开发环境
安装cygwin: 由于NDK编译代码时必须要用到make和gcc,所以你必须先搭建一个linux环境, cygwin是一个在windows平台上运行的unix模拟环境,它对于学习unix/linux ...
- Nginx日志切割工具——logrotate 使用记录
1.安装 logrotate是Linux系统自带,无需安装 2.配置 进入[/etc/logrotate.d/nginx]文件修改配置 # 需要备份的日志路劲,一个或多个都可以 /data/logs/ ...
- bzoj 2002 LinkCutTree
我的第一道LCT题(居然1A,O(∩_∩)O哈哈~) 题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2002 大概题意: 给一颗有根树,维护每个 ...
- ArrayList源码阅读----JDK1.8
//定义一个默认的长度10 private static final int DEFAULT_CAPACITY = 10; //定义空的数组 private static final Object[] ...
- 为什么TCP连接需要三次握手分开需要四次握手?
TCP的三次握手和四次断开TCP是一个面向连接的服务,面向连接的服务是电话系统服务模式的抽象,每一次完整的数据传输都必须经过建立连接,数据传输和终止连接3个过程,TCP建立连接的过程称为三次握手,下面 ...
- [转]对Why Scrum will never work的评论
近来,Maurits的一篇博文“Why Scrum will never work” 一石激起千层浪.著名技术分享网站酷壳(http://coolshell.cn/articles/5044.html ...
- C#笔试题面试题锦集(全)总20篇
前些时候找过一次工作,收集了很多不错的笔试题目.共享一下:) C#笔试题面试题锦集(20) 微软应试题目 (2010-01-15 21:32) C#笔试题面试题锦集(19) 雅虎C#题目 (2010- ...
- vc预处理
VC 编译命令开关 vc可以可以通过Settings -->Project-->C/C++-->Customize来设置这个编译开关 /C:在预处理输出中保留注释语句 /c:只编译, ...
- Orchard运用 - 定制呈现最新博客文章
每个博客系统为了吸引更多访问量,一般都会在首页或侧边栏列举一些最新文章/随笔以获取更多点击.其实也就是查询出最新的几篇文章并按照简练的方式呈现,比如一般都只有标题及其对应的链接,有时也会标注一下作者和 ...
- 84. Largest Rectangle in Histogram-hard
84. Largest Rectangle in Histogram 题目 Given n non-negative integers representing the histogram's bar ...