构建查询表达式

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

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;

待续!

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

  1. lambda表达式浅析【C++学习笔记】

    lambda表达式浅析[C++学习笔记] 基本用法: auto f = [/*捕获列表*/](/*参数*/)->int /*后置返回值类型*/{/** 函数体*/}; 捕获列表: [] : 不捕 ...

  2. 《数据结构、算法与应用 —— C++语言描述》学习笔记 — 竞赛树

    <数据结构.算法与应用 -- C++语言描述>学习笔记 - 竞赛树 一.赢者树 二.二叉树的数组描述(补充) 1.声明 2.实现 三.赢者树 1.抽象数据类型 2.赢者树的表示 3.声明 ...

  3. IBatis.Net学习笔记六--再谈查询

    在IBatis.Net学习笔记五--常用的查询方式 中我提到了一些IBatis.Net中的查询,特别是配置文件的写法. 后来通过大家的讨论,特别是Anders Cui 的提醒,又发现了其他的多表查询的 ...

  4. JavaWeb-综合案例(用户信息)-学习笔记05【分页查询功能】

    Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb-综合案例(用户信息)-学习笔记01[列表查询] JavaWeb-综合案例(用户信息)-学习笔记02[登录功能] JavaWeb-综合案 ...

  5. JavaWeb-综合案例(用户信息)-学习笔记01【列表查询】

    Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb-综合案例(用户信息)-学习笔记01[列表查询] JavaWeb-综合案例(用户信息)-学习笔记02[登录功能] JavaWeb-综合案 ...

  6. oracle修改asm参数文件,学习笔记:Oracle RAC参数文件管理 修改创建asm中的spfile文件...

    天萃荷净 Oracle rac创建修改asm中的spfile文件内容 create spfile to asm --查看sid SQL> show parameter instance_name ...

  7. 三、MySQL子查询学习笔记(标量子查询、列子查询、行子查询、表子查询 详解)

    三.MySQL子查询学习笔记 7:子查询 含义: 一条查询语句中又嵌套了另一条完整的select语句,其中被嵌套的select语句,称为子查询或内查询:在外面的查询语句,称为主查询或外查询 分类: 一 ...

  8. oracle 最大值及其_学习笔记:Oracle优化 SQL查询最大值 最小值时的优化方法案例...

    天萃荷净 select max(id),min(id) from table优化,分享开发DBA需求,在SQL语句查询最大值.最小值数据时的优化方式案例 1.查看数据库版本 SQL> selec ...

  9. 《游戏设计艺术(第2版)》——学习笔记(20)第20章 世界中的角色

    <游戏设计艺术(第2版)>学习笔记(20) 第20章 世界中的角色 游戏角色的本质 小说角色 电影角色 游戏角色 化身 理想型 白板 创造令人信服的游戏角色 角色窍门1:列出角色的功能 角 ...

最新文章

  1. ASP .NET Core使用connection string连接MySQL/MariaDB,并设置UTF-8编码
  2. webpack.DefinePlugin使用介绍
  3. java awt 初始化_Java awt项目开发
  4. SCons: A software construction tool
  5. cf1453B. Suffix Operations
  6. 【LeetCode笔记】621. 任务调度器(Java、桶)
  7. 柱状图中xy轴怎么出现_如果制砂机设备在工作中出现堵料现象该怎么办?
  8. php中声明空数组,总结PHP中初始化空数组的最佳方法
  9. mysql in 文本_MySQL_mysql 的load data infile,LOAD DATA INFILE语句从一个文本文 - phpStudy...
  10. tcp协议和udp协议区别_TCP和UDP协议有什么区别?
  11. 数据切分——Mysql分区表的建立及性能分析
  12. Azkaban时区问题导致调度差1天
  13. onCreateView中加载大位图
  14. 一个故事讲完CPU的工作原理 侵删
  15. python模拟人工滑动_python selenium模拟滑动操作
  16. linux登录认证过程,Linux的SSH免密登录认证过程研究
  17. com.itextpdf.text.exceptions.IllegalPdfSyntaxException: Unbalanced begin/end text operators.
  18. ZBrush笔刷整理大合集
  19. unzip:unzip解压文件到指定目录
  20. PPPwizard1.4.3软件使用说明中文翻译稿

热门文章

  1. 国产微服务网关Apache APISIX安装
  2. 传输层协议(TCP/UDP)介绍
  3. sudo运行程序遇到的问题
  4. postgresql关闭自动提交
  5. Fedora开启telnet服务
  6. 51nod 1087 1 10 100 1000
  7. The way of Webpack learning (II.) -- Extract common code(多页面提取公共代码)
  8. 【三分+枚举】LNOI2017 d1t1 期末考试
  9. LeetCode Climbing Stairs
  10. ThinkPHP函数详解:M方法