3

I'm trying to understand why Linq is generating the SQL that it is for the statement below:

var dlo = new DataLoadOptions();
dlo.LoadWith<TemplateNode>(x => x.TemplateElement);
db.LoadOptions = dlo;

var data = from node in db.TemplateNodes
           where node.TemplateId == someValue
           orderby node.Left
           select node;

Which generates the following SQL:

SELECT [t2].[Id],
       [t2].[ParentId],
       [t2].[TemplateId],
       [t2].[ElementId],
       [t2].[Left]  AS [Left],
       [t2].[Right] AS [Right],
       [t2].[Id2],
       [t2].[Content]
FROM   (SELECT ROW_NUMBER() OVER (ORDER BY [t0].[Left]) AS [ROW_NUMBER],
               [t0].[Id],
               [t0].[ParentId],
               [t0].[TemplateId],
               [t0].[ElementId],
               [t0].[Left],
               [t0].[Right],
               [t1].[Id]                                AS [Id2],
               [t1].[Content]
        FROM   [dbo].[TemplateNode] AS [t0]
               INNER JOIN [dbo].[TemplateElement] AS [t1]
                 ON [t1].[Id] = [t0].[ElementId]
        WHERE  [t0].[TemplateId] = 16 /* @p0 */) AS [t2]
WHERE  [t2].[ROW_NUMBER] > 1 /* @p1 */
ORDER  BY [t2].[ROW_NUMBER]

There is a Foreign Key from TemplateNode.ElementId to TemplateElement.Id.

I would have expected the query to produce a JOIN, like so:

SELECT * FROM TemplateNode
INNER JOIN TemplateElement ON TemplateNode.ElementId = TemplateElement.Id
WHERE TemplateNode.TemplateId = @TemplateId

As per the suggestions in the answers to this question I have profiled both queries and the JOIN is 3 times faster than the nested query.

I'm using a .NET 4.0 Windows Forms app to test with SQL Server 2008 SP2 64bit developer edition.

Community
  • 1
  • 1
Greg B
  • 14,597
  • 18
  • 87
  • 141

2 Answers2

1

The only reason that LINQ-SQL would generate the ROW_NUMBER query is due to the Skip Method. As bizare as the above SQL seems, I think within T-SQL there is no construct for simple paging like MySQL's Limit 10,25, so you get the above SQL when using Skip and Take.

I would assume that there is a Skip being used for paging purposes and LINQ-SQL is modifying the query. If you use an application like LINQ-Pad you can run different LINQ queries to see their generated SQL.

Hux
  • 3,102
  • 1
  • 26
  • 33
0

Your example of a join is not equivalent. You cannot get the ROW_NUMBER and subsequently select only rows WHERE ROW_NUMBER > 1 with a simple join. You would have to do a sub-select or similar to get this result.

Ben English
  • 3,900
  • 2
  • 22
  • 32
  • Ben, Thanks for your answer. I'm not sure you haven't misread my question. I'm not after the `ROW_NUMBER`, I simply want the result of the `JOIN` in the second SQL statement, but Linq2SQL is generating the 1st query with the sub-query in it. I want to know what is causing this so that I can mitigate it. – Greg B Mar 12 '12 at 18:44