表达式树 php,Linux_LINQ学习笔记:表达式树,构建查询表达式 本节中, 我们 - phpStudy...

构建查询表达式

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

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> lambda = Expression.Lambda>(comparison,p);

10: //转换为委托

11: Func runnable = lambda.Compile();

12: Console.WriteLine(runnable(“James”)); //False

13: Console.WriteLine(runnable(“dog”)); //True

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

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

待续!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值