在前面的系列中,我们已经讨论了LINQ简单查询的大部分特性,了解了LINQ的支持计术和语法形式。至此,我们应该可以创建出大部分相对简单的LINQ查询。在本篇中,除了对前面的知识做个简单的总结,还会介绍几种创建更复杂查询的方式,让我们在面对更复杂的场景时也能轻松面对,包括:子查询、创建策略和数据转换。
子查询
在创建一个复杂的查询时,通常我们需要用到子查询。相信大家都记得SQL查询里的子查询,在创建LINQ查询时也是如此。在LINQ中,对于方法语法,一个子查询包含在另外一个查询的lambda表达式中,对于查询表达式语法来讲,所有不是from子句中引用的查询都是子查询。
下面的查询使用子查询来对last name进行排序,语句中的n.Split().Last()就是一个子查询:
string[] names = { "David Tim", "Tony Sin", "Rager Witers" }; IEnumerable<string> query = names.OrderBy(n => n.Split().Last());
子查询的作用域限定在当前的lambda表达式中,并且可以引用外部lambda表达式的参数(查询表达式的范围变量)。
下面的查询获取所有长度最短的名字(注意:可能有多个):
static void TestSubQuery() { string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" }; // 获取所有长度最短的名字(注意:可能有多个) IEnumerable<string> outQuery = names .Where(n => n.Length == names // 感谢A_明~坚持的指正,这里应该为== .OrderBy(n2 => n2.Length) .Select(n2 => n2.Length).First()); // Tom, Jay" // 与上面方法语法等价的查询表达式 IEnumerable<string> outQuery2 = from n in names where n.Length == // 感谢A_明~坚持的指正,这里应该为== (from n2 in names orderby n2.Length select n2.Length).First() select n; // 我们可以使用Min查询运算符来简化 IEnumerable<string> outQuery2 = from n in names where n.Length == names.Min(n2 => n2.Length) select n; }