LINQ之路:查询表达式

开发 后端
LINQ的语法本质是通过扩展的方法和Lambda表达式来创建查询,今天我们将介绍的是查询表达式(Query Expression)。

  书写LINQ查询时又两种语法可供选择:方法语法(Fluent Syntax)和查询表达式(Query Expression)。

  LINQ方法语法的本质是通过扩展方法和Lambda表达式来创建查询。C# 3.0对于LINQ表达式还引入了声明式的查询表达式,也叫查询语法,通常来讲,它是创建LINQ查询的更加快捷的方式。尽管通过查询语法写出的查询比较类似于SQL查询,但实际上查询表达式的产生并不是建立在SQL之上,而是建立在函数式编程语言如LISP和Haskell中的list comprehensions(列表解析)功能之上。本篇会对LINQ查询语法进行详细的介绍。

  我们在前一篇LINAQ方法语法中所举的示例:获取所有包含字母”a”的姓名,按长度排序并将结果转为大写。下面是与之等价的查询表达式语法:

  1.   staticvoidMain(string[] args)  
  2.   {  
  3.   string[] names = { "Tom""Dick""Harry""Mary""Jay"};  
  4.   IEnumerable<string>query =  
  5.   from n innames  
  6.   wheren.Contains("a"//Filter elements  
  7.   orderby n //Sort elements  
  8.   select n.ToUpper(); //Translate each element  
  9.   foreach(stringname inquery)  
  10.   Console.WriteLine(name);  
  11.   } 

  查询表达式总是以from子句开始,以select或者group子句结束。From子句定义了查询的范围变量(range variable),可以认为该变量是对输入sequence的一个遍历,就像foreach做的那样。下面这幅图描述了查询表达式的完整语法:

  当然,.NET公共语言运行库(CLR)并不具有查询语法的概念。编译器会在程序编译时把查询表达式转换为方法语法,即对扩展方法的调用。这意味着,我们用查询表达式写出来的LINQ查询都有等价的方法语法。对于上例中的查询表达式,编译器会转换成下面的方法语法:

 

  1.   IEnumerable<string>query = names  
  2.   .Where (n => n.Contains("a"))  
  3.   .OrderBy(n => n.Length)  
  4.   .Select (n => n.ToUpper()); 

 

  然后,应用编译器对于方法语法的处理规则,上面的Where, OrderBy, Select查询运算符会绑定到Enumerable类中的相应扩展方法。

  范围变量

  范围变量是紧随from关键字之后定义的变量,一个范围变量指向当前操作符所对应的输入sequence中的当前元素。在我们的示例中,范围变量出现在每一个查询子句中,但要注意的是,变量实际是对不同sequence的遍历,因为Where、OrderBy、Select会有不同的输入sequence:

 

  1.   IEnumerable<string>query =  
  2.   from n innames //n是我们定义的范围变量  
  3.   wheren.Contains("a"//n直接来自names array  
  4.   orderby n.Length //n来自filter之后的subsequent  
  5.   select n.ToUpper(); //n来自OrderBy之后的subsequent 

 

  当 编译器把上面的查询语法翻译成方法语法后,我们会更清楚的看到范围变量的这种行为:

 

  1.   IEnumerable<string>query2 = names  
  2.   .Where(n => n.Contains("a")) //n直接来自names array  
  3.   .OrderBy(n => n.Length) //n来自filter之后的subsequent  
  4.   .Select(n => n.ToUpper()); //n来自OrderBy之后的subsequent  

 

  除了from关键字后面的范围变量,查询表达式还允许我们通过下面的子句引入新的范围变量:

  let

  into

  额外的from子句

  稍后我们会在“LINQ中的子查询、创建策略和数据转换”一篇中讨论他们的使用方法和适用场景。

  查询表达式和方法语法

  查询表达式和方法语法各有所长。对下面的场景来讲,用查询表达式写出来得查询会更加简洁:

  使用let关键字引入新的范围变量

  在SelectMany、Join或GroupJoin后引用外部范围变量时

  在简单的使用Where、OrderyBy、Select时,两种语法结构并没有大的差别,此时可以根据你的喜好任意选择。

  对于只有单个查询运算符组成的查询,方法语法会更加简短和易于理解。

  ***,对于没有对应查询表达式关键字的查询运算符,我们就只能选择方法语法了。下面是存在对应查询表达式关键字的运算符:Where、Select、SelectMany、OrderBy、ThenBy、OrderByDescending、ThenByDescending、GroupBy、Join、GroupJoin。

  组合查询语法

  当一个查询运算符没有对应的查询语法时,我们可以组合使用查询语法和方法语法。唯一的约束是查询中的每一个查询语法部分必须是完整的,如以from开始以select或group结束。如下例:

 

  1.   string[] names = { "Tom""Dick""Harry""Mary""Jay"};  
  2.   //计算包含字母”a”的姓名总数  
  3.   intmatches = (from n innames wheren.Contains("a") select n).Count(); //3//按字母顺序排序的***个名字  
  4.   stringfirst = (from n innames orderby n select n).First(); //Dick 

 

  这种组合语法通常在书写更加复杂的查询时会具有优势,像上面这种简单的查询,我们只需要使用方法语法就能收到很好的效果:

  1.   intmatches = names.Where(n => n.Contains("a")).Count(); //3  
  2.   stringfirst = (names.OrderBy(n => n)).First(); //Dick 

原文链接:http://www.cnblogs.com/lifepoem/archive/2011/10/28/2227735.html

【编辑推荐】

  1. Linq to xml操作XML
  2. XML之父解读未来互联网"游戏化"的三个真谛
  3. Ajax和Web服务数据格式:XML SOAP HTML
  4. 超强解析XML——简单直接的来
  5. 解析PHP中的XML数据
责任编辑:彭凡 来源: 博客园
相关推荐

2009-09-10 15:35:07

LINQ查询表达式

2009-08-27 09:13:28

LINQ查询表达式

2009-09-07 17:18:33

LINQ查询表达式

2009-09-11 09:53:16

Linq查询表达式

2009-09-17 11:08:55

LINQ查询表达式

2009-09-17 09:09:50

Lambda表达式Linq查询

2009-09-11 12:32:33

LINQ表达式

2009-09-15 15:18:00

Linq Lambda

2009-09-09 13:01:33

LINQ Lambda

2009-09-17 14:21:19

LINQ表达式

2009-09-11 09:48:27

Linq Lambda

2009-09-09 17:45:07

Linq表达式

2009-06-12 09:44:04

LINQ查询复合from子句

2009-09-15 17:30:00

Linq Lambda

2009-09-17 09:15:49

Linq表达式树

2009-09-17 10:40:22

Linq Lambda

2009-09-17 09:44:54

Linq Lambda

2009-03-23 10:47:43

数据库SQLLINQ

2009-09-17 14:24:35

LINQ表达式

2009-09-09 17:14:17

Linq lambda
点赞
收藏

51CTO技术栈公众号