为什么以下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来自哪里?

你仍然可以使它像这样清洁:

 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)的事实在这里是棘手的部分。

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

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

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

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

试试这样的事情:

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

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

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