日期:2014-05-20  浏览次数:21063 次

linq子查询--学习linq的资料和笔记(五)

万事不要操之过急,循序渐进就好。


在sql中我们会用到子查询来进行复杂一些的查询工作,在linq中同样可以使用子查询,不过如果是连接数据库的话使用子查询会只连接一次数据库进行查询,而如果是内存中的数据,则使用子查询会效率低下,每次迭代返回至时都会执行子查询,那么就应该将子查询分离出来。

在linq的方法语法中,子查询包含在父查询的lambda表达式中,即都要写在匿名方法中, 查询表达式  除了from字句不能使用子查询 其他都可以使用子查询

以下内容来自博客园

在创建一个复杂的查询时,通常我们需要用到子查询。相信大家都记得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.OrderBy(n2 => n2.Length)
                    .Select(n2 => n2.Length).First());      // Tom, Jay"
           // 与上面方法语法等价的查询表达式
            IEnumerable<string> outQuery2 =
                from n in names
                where n.Length ==(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;
        }

因为外部范围变量在子查询的作用域内,所以我们不能再次使用n作为内部查询的范围变量。

一个子查询在包含它的lambda表达式执行时被执行,这意味着子查询的执行取决于外部查询。需要注意的是:本地查询(LINQ to Objects)和解释查询(LIQN to SQL)对于子查询的处理方式是不一样的。对于本地查询,对于外部查询的每一次循环,子查询都会被重新执行一次。在稍后“解释查询”一篇中, 我们会看到,外部查询和子查询是作为一个单元进行处理的,这样,只需一次到远程数据源(如数据库)的连接。所以上面的例子对于一个数据库查询来说非常适合,但对于一个内存中的集合来说却效率低下,这时我们可以把子查询分离出来对让它只执行一次(这样它不再是一个子查询)。


int shortest = names.Min(n => n.Length);
            IEnumerable<string> query = from n in names
                                        where n.Length == shortest
                                        select n;

在延迟执行一篇中,我们说到元素和集合运算符如First和Count会让一个查询立即执行。但对一个子查询来说,即使是元素和集合运算符也不会改变外部查询延迟执行的特性。这是因为,不管是对本地查询还是通过表达式树访问的解释查询,子查询是间接调用的。