当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > LINQ学习笔记:表达式树

ASP.NET
asp.net下用服务器端代码解决浏览器兼容性问题
asp.net 安全的截取指定长度的html或者ubb字符串
asp.net 在线编辑word文档 可保存到服务器
asp.net 提高网站速度及如何利用缓存
asp.net 修改/删除站内目录操作后Session丢失问题
asp.net URL重写简化版 速学URL重写
asp.net EncryptHelper 加密帮助类
asp.net JSONHelper JSON帮助类
C# 调用存储过程简单完整的实例代码
vs2008 安装失败的总结与分享
HttpHandler HttpModule入门篇
ASP.NET(AJAX+JSON)实现对象调用
Asp.net 基于Cookie简易的权限判断
asp.net通过HttpModule自动在Url地址上添加参数
asp.net 字符串、二进制、编码数组转换函数
ASP.NET操作Excel备忘录
记录游客页面访问IP的简易实现代码 (asp.net+txt)
比较简单的将数据信息导入wrod文档方案(C# for word)
增加asp.net应用程序性能的20种方法(简单有效)
ASP.NET 图片防盗链的实现原理分析

ASP.NET 中的 LINQ学习笔记:表达式树


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-28   浏览: 72 ::
收藏到网摘: n/a

构建查询表达式

本节中, 我们假设我们拥有一个这样的实体类:

 1: [Table] public partial class Product
 2:  
 3: {
 4:  
 5: [Column(IsPrimaryKey=true)] public int ID;
 6:  
 7: [Column] public string Description;
 8:  
 9: [Column] public bool Discontinued;
 10:  
 11: [Column] public DateTime LastSale;
 12:  
 13: }

 

委托 VS 表达式树

让我们回忆一下:

1. 本地查询,使用的Enumerable操作符,使用委托

2. 解释查询(Interpreted Query),使用Queryable操作符,使用表达式树

我们可以比较一下Where操作符在Enumerable和Queryable当中的签名:

 1: public static IEnumerable Where (this
 2:  
 3: IEnumerable source,
 4:  
 5: Funcbool> predicate)
 6:  
 7: public static IQueryable Where (this
 8:  
 9: IQueryable source,
 10:  
 11: Expressionbool>> predicate)

 

当把他们嵌入到一个查询当中的时候,Lamdba表达式看上去都是一样的,无论它是绑定到Enumerable或者Queryable:

 1: IEnumerable q1 = localProducts.Where
 2:  
 3: (p => !p.Discontinued);
 4:  
 5: IQueryable q2 = sqlProducts.Where
 6:  
 7: (p => !p.Discontinued);

 

当你将一个Lambda表达式赋给一个中间变量的时候, 你必须显示地指示是将它绑定到委托(Func<>)或者是表达式树(Expression<>>)

编译表达式树

通过调用Compile我们可以将一个表达式树转换为委托. 当我们编写的方法返回可重用的表达式时这回带来特别的价值. 为了演示,我们将给Product类增加一个静态方法, 其返回一个bool值用于断言那些Discontinued并且在过去30天内销售的产品.

 1: public partial class Product
 2:  
 3: {
 4:  
 5: public static Expressionbool>>
 6:  
 7: IsSelling()
 8:  
 9: {
 10:  
 11: return p => !p.Discontinued &&
 12:  
 13: p.LastSale > DateTime.Now.AddDays (-30);
 14:  
 15: }
 16:  
 17: }

 

(注:对于类似的扩展方法,我们应该编写一个全新的文件从而避免去覆盖由VS的设计器自动产生的文件.)

此方法可以同时被用于本地查询和解释查询,如下所示:

 1: void Test( )
 2:  
 3: {
 4:  
 5: var dataContext = new MyTypedDataContext (“connectionString”);
 6:  
 7: Product[] localProducts =
 8:  
 9: dataContext.Products.ToArray( );
 10:  
 11: IQueryable sqlQuery =
 12:  
 13: dataContext.Products.Where(Product.IsSelling());
 14:  
 15: IEnumerable localQuery =
 16:  
 17: localProducts.Where(Product.IsSelling.Compile());
 18:  
 19: }

 

相比之下, 我们并不能将一个委托转换为表达式树,这也使得表达式树更加有用.

AsQueryable

使用AsQueryable操作符可以编写用于操作本地或者远程序列的查询:

 1: IQueryable FilterSortProducts
 2:  
 3: (IQueryable input)
 4:  
 5: {
 6:  
 7: return from p in input
 8:  
 9: where
 10:  
 11: order by …
 12:  
 13: select p;
 14:  
 15: }
 16:  
 17: void Test()
 18:  
 19: {
 20:  
 21: var dataContext = new MyTypedDataContext (“connectionString”);
 22:  
 23: Product[]localProducts =
 24:  
 25: dataContext.Products.ToArray();
 26:  
 27: var sqlQuery =
 28:  
 29: FilterSortProducts (dataContext.Products);
 30:  
 31: var localQuery =
 32:  
 33: FilterSortProducts (localProducts.AsQueryable());
 34:  
 35: }

 

AsQueryable对本地查询包装了一层Queryable<>外衣,这使得接下来的子查询都是针对表达式树的.当你开始枚举结果集的时候,表达式树会被隐式编译转换成为本地查询然后向往常一直执行.

表达式树

我们之前说过将一个Lambda表达式赋值给一个Expression类型变量会引起C#编译器解析表达式树.使用编程手段, 我们可以在运行时做相同的事情-换句话说, 从零开始动态创建表达式树. 结果集可以被转换为Expression并被使用于LINQ to SQL查询中,或者通过调用Compile将其转换为委托.

表达式DOM

一个表达式树是一个小型DOM. 每一个节点表示一个System.Linq.Expressions命名空间下的一个类型. 其基类是Expression(非泛型),而泛型Expression实际上是表示类型化的Lambda表达式.

Expression<>的基类是非泛型的LambdaExpression类, LambdaExpression提供了针对Labmbda表达式树的统一类型:任何Expression<>都看可以被转换为LambdaExpression.

为了创建表达式树, 我们并不需要直接实例化节点类,而是通过调用Expression类提供的静态方法:

 1: //创建输入参数s
 2: ParameterExpression p = Expression.Parameter(typeof(string), “s”);
 3: //参数属性Length
 4: MemberExpression stringLength = Expression.Property(p, “Length”);
 5: //常量5
 6: ConstantExpression five = Expression.Constant(5);
 7: //比较操作符
 8: BinaryExpression comparison = Expression.LessThan(stringLength, five);
 9: Expression<string,bool>> lambda = Expression.Lambda<string,bool>>(comparison,p);
 10: //转换为委托
 11: Func<string, bool> runnable = lambda.Compile();
 12: Console.WriteLine(runnable(“James”)); //False
 13: Console.WriteLine(runnable(“dog”)); //True

 

此示例动态创建了一个如下的Lambda表达式:

 1: Expression<string, bool>> f = s => s.Length < 5;

 

待续!