当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > LINQ学习笔记:复合查询和Lambda表达式语法

ASP.NET
使用函数传递参数来执行相应的数据库操作
如何实现在窗体和窗体之间进行传递数据
ASP.NET中文显示之两种解决方法
ASP.NET、JSP及PHP之间的抉择
ASP.NET 2.0发送电子邮件中存在的问题
谈谈HtmlControl与WebControl的区别与用途
从ASP.NET 1.1升级到ASP.NET 2.0要考虑的Cookie问题
通过系统配置来提高ASP.NET应用程序的稳定性
妙用ASP2.0中的URL映射改变网址
AJAX实现web页面中级联菜单的设计
ASP.NET跨页面传值技巧总结
再议ASP.NET DataGrid控件中的“添加新行”功能
Geometry 对象浅析
重构CollapsibleSplitter
如何利用.NET Framework使用RSS feed
ASP.NET获取IP与MAC地址的方法
在ASP.NET 2.0中使用样式、主题和皮肤
ASP.NET中为GridView添加删除提示框
ASP.NET 2.0,无刷新页面新境界
看看一个.net版对话框控件

ASP.NET 中的 LINQ学习笔记:复合查询和Lambda表达式语法


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

复合查询

前一节中, 我们写了一个查询来将分解那些包含一个字母a, 按长度排序, 并且最后转换成大写的字符串. 我们还有另外一种复合查询的写法:

 1: //前面我们使用的写法
 2: string[] names = { "James","Jack","Harris"};
 3:  
 4: IEnumerable<string> query = names.Where(n => n.Contains ("a"))
 5: .OrderBy (n => n.Length).Select (n => n.ToUpper( ));
 6:  
 7: //组合查询的写法
 8: string[] names = { "James","Jack","Harris"};
 9: IEnumerable<string> q = from n in names where n.Contains("a")
 10: orderby n.Length
 11: select n.ToUpper();
 12: 
 13: foreach(string s in q)
 14: Console.Write(s + ","); //JACK,JAMES,HARRIS,

 

一个复合查询总是开始于from语句结束于select或者group语句. from语句声明了一个迭代变量, 此变量代表输入序列中的每一个元素, 类似foreach语法中的变量. 编译器会将复合查询翻译成Lambda表达式, 类似于foreach表达式会被翻译成调用GetEnumerator和MoveNext方法. 这意味着任何你可以使用的复合查询同样也可以使用Lambda表达式来完成. 例如上面的例子, 编译器将会翻译成这样:

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

 

迭代变量

紧跟在from关键字之后的标识符称为迭代变量, 在我们的例子中, 迭代变量n出现在每一个查询中的每一个从句. 然后, 此变量实际上枚举了每一个从句中的不同序列中的元素:

 1: from n in names // n 是我们的迭代变量
 2: where n.Contains ("a") // n = 直接来自于数组
 3: orderby n.Length // n = 被过滤后的
 4: select n.ToUpper(); // n = 排序过的

 

如果检查一下编译器帮我们生成的使用Lambda表达式的版本就可以看得更加清晰一点:

 1: names.Where (n => n.Contains ("a"))
 2: .OrderBy (n => n.Length)
 3: .Select (n => n.ToUpper());

 

n都是只属于各自Lambda表达式的范围里面的.

查询语法 VS SQL语法

LINQ的复合查询语法看起来和SQL语法非常像, 然后他们是非常不同的. 一个LINQ查询说到底还是一个C#表达式, 因为必须要遵循标准的C#规则. 例如, 在LINQ中, 你不能使用一个未声明的变量. 而在SQL中, 在from语句定义之前你已经可以在select中引用一个表的别名了.

在LINQ中的子查询仅仅是另外一个C#表达式, 因此并不需要有什么特殊的语法. 而子查询在SQL当中通常要受到一些特殊规则的限制.

在LINQ中, 整个数据处理流程是从左到右的. 而在SQL中, 这个顺序则更加随机.

一个LINQ查询构成一个传送带, 或者一个管道, 其中的操作符接受和处理有序序列. 而SQL查询则构成的语法网更多的是处理无序集合.

查询语法和 Lambda表达式

复合查询和Lambda表达式语法更有优点. 复合查询对于符合以下情况的查询更加简单一些:

1. let从句来一个迭代变量后用于代表一个新的变量

 1: var list = new List<int>() { 1, 2, 3 };
 2: var query = from i in list
 3: let j = i + 2
 4: let k = j * j
 5: select new { i, j, k };

 

2. SelectMany, Join或者GroupJoin紧跟着一个外部的迭代变量引用

至于Where, OrderBy和Select的使用, 两种表达语法都可以工作的很好, 如何使用, 更多的取决于个人习惯.

对于那些只由单一操作符构成的查询来说, Lambda表达式语法更加简短,简洁一点.

最后, 有很多的操作符是没有对应的复合查询关键字的, 对于这些操作符你只能使用Lambda表达式语法, 或者至少部分使用, 它们是:

Where, Select, SelectManager, OrderBy, ThenBy, OrderByDescending, ThenByDescending, Group, Join, GroupJoin

混合的查询语法

如果一个查询操作符没有对应的复合查询支持, 你可以混合使用复合查询和Lambda表达式语法. 唯一的限制是每一个复合组件都必须被完成(例如从一个form从句开始并且结束于一个select或者group从句).

例如:

 1: string[] names = { "James","Jack","Harris"};
 2: int myCount = (from n in names
 3: where n.Contains ("J")
 4: select n
 5: ).Count();
 6: Console.WriteLine(myCount); //2

 

有一点是非常重要的, 你不能单一的偏向于喜欢复合查询语法或者Lambda表达式语法, 更多的应该是根据功能的需要和简单性来做选择. 待续!