为什么以下linq to sql查询生成子查询?

时间:2009-12-14 19:45:46

标签: c# linq-to-sql

我做了以下查询:

var list = from book in books
          where book.price > 50
          select book;

list = list.Take(50);

我希望上面的内容能够生成:

SELECT top 50 id, title, price, author
FROM Books
WHERE price > 50

但它会产生:

SELECT
[Limit1].[C1] as [C1]
[Limit1].[id] as [Id], 
[Limit1].[title] as [title], 
[Limit1].[price] as [price], 
[Limit1].[author]
FROM (SELECT TOP (50) 
             [Extent1].[id] as as [Id], 
             [Extent1].[title] as [title], 
             [Extent1].[price] as [price], 
             [Extent1].[author] as [author]
      FROM Books as [Extent1]
      WHERE [Extent1].[price] > 50
     ) AS [Limit1]

为什么上面的linq查询会生成子查询以及C1来自哪里?

5 个答案:

答案 0 :(得分:2)

免责声明:我以前从未使用过LINQ ......

我的猜测是分页支持?我想你有某种Take(50, 50)方法可以获得50条记录,从记录50开始。看看查询生成的SQL,你可能会发现它使用类似的子查询结构来允许它返回查询中的任何50行,大约是它返回前50行的时间量。

在任何情况下,嵌套的子查询都不会增加任何性能开销,因为它在编译执行计划期间会自动优化。

答案 1 :(得分:1)

你仍然可以像这样清洁:

var c = (from co in db.countries
                    where co.regionID == 5
                    select co).Take(50);

这将导致:

Table(country).Where(co => (co.regionID = Convert(5))).Take(50)

相当于:

SELECT TOP (50) [t0].[countryID], [t0].[regionID], [t0].[countryName], [t0].[code]
FROM [dbo].[countries] AS [t0]
WHERE [t0].[regionID] = 5

编辑:评论,它不一定是因为单独的Take(),你仍然可以这样使用它:

var c = (from co in db.countries
                     where co.regionID == 5
                     select co);
            var l = c.Take(50).ToList();

结果与以前相同。

SELECT TOP (50) [t0].[countryID], [t0].[regionID], [t0].[countryName], [t0].[code]
FROM [dbo].[countries] AS [t0]
WHERE [t0].[regionID] = @p0

你写IQueryable = IQueryable.Take(50)的事实在这里很棘手。

答案 2 :(得分:0)

子查询是为了投影目的而生成的,当您从多个表中选择一个匿名对象时更有意义,然后外部查询用于收集结果。

尝试使用类似的内容:

from book in books
where price > 50
select new 
{
  Title = book.title,
  Chapters = from chapter in book.Chapters
             select chapter.Title
}

答案 3 :(得分:0)

是不是第一个查询返回总行数而第二个是根据对.Take()方法的调用提取行子集的情况?

答案 4 :(得分:0)

  1. 我同意@Justin Swartsel。没有涉及错误,所以这主要是学术问题。
  2. Linq-to-SQL努力生成高效运行的SQL(在您的情况下就是这样)。
    1. 但它没有做任何努力来生成人类可能会创建的传统 SQL。
  3. Linq-to-SQL实现者可能使用构建器模式来生成SQL。
    1. 如果是这样的话,附加一个子串(或在这种情况下是子查询)比回溯并在SELECT子句中插入'TOP x'片段更容易。