- Rongsen.Com.Cn 版权所有 2008-2010 京ICP备08007000号 京公海网安备11010802026356号 朝阳网安编号:110105199号
- 北京黑客防线网安工作室-黑客防线网安服务器维护基地为您提供专业的
服务器维护
,企业网站维护
,网站维护
服务 - (建议采用1024×768分辨率,以达到最佳视觉效果) Powered by 黑客防线网安 ©2009-2010 www.rongsen.com.cn
作者:黑客防线网安SQL维护基地 来源:黑客防线网安SQL维护基地 浏览次数:0 |
构建查询表达式
本节中, 我们假设我们拥有一个这样的实体类:
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;
待续!
我要申请本站:N点 | 黑客防线官网 | |
专业服务器维护及网站维护手工安全搭建环境,网站安全加固服务。黑客防线网安服务器维护基地招商进行中!QQ:29769479 |