sql >> Base de Datos >  >> RDS >> Sqlserver

LINQ to SQL Take w/o Skip provoca varias declaraciones SQL

Primero:algunos razonamientos para el error Take.

Si simplemente tomas , el traductor de consultas solo usa top. Top10 no dará la respuesta correcta si la cardinalidad se rompe al unirse a una colección secundaria. Entonces, el traductor de consultas no se une a la colección secundaria (en su lugar, vuelve a consultar por los secundarios).

Si Salta y Toma , luego el traductor de consultas se activa con algo de lógica RowNumber sobre las filas principales... estos números de fila le permiten tomar 10 padres, incluso si son realmente 50 registros debido a que cada padre tiene 5 hijos.

Si Omite(0) y Toma , Omitir se elimina como una operación no realizada por el traductor; es como si nunca hubiera dicho Omitir.

Este va a ser un salto conceptual difícil desde donde está (llamando Saltar y tomar) a una "solución alternativa simple". Lo que tenemos que hacer es forzar que la traducción ocurra en un punto en el que el traductor no pueda eliminar Saltar (0) como una no operación. Necesitamos llamar a Skip y proporcionar el número omitido en un momento posterior.

DataClasses1DataContext myDC = new DataClasses1DataContext();
  //setting up log so we can see what's going on
myDC.Log = Console.Out;

  //hierarchical query - not important
var query = myDC.Options.Select(option => new{
  ID = option.ParentID,
  Others = myDC.Options.Select(option2 => new{
    ID = option2.ParentID
  })
});
  //request translation of the query!  Important!
var compQuery = System.Data.Linq.CompiledQuery
  .Compile<DataClasses1DataContext, int, int, System.Collections.IEnumerable>
  ( (dc, skip, take) => query.Skip(skip).Take(take) );

  //now run the query and specify that 0 rows are to be skipped.
compQuery.Invoke(myDC, 0, 10);

Esto produce la siguiente consulta:

SELECT [t1].[ParentID], [t2].[ParentID] AS [ParentID2], (
    SELECT COUNT(*)
    FROM [dbo].[Option] AS [t3]
    ) AS [value]
FROM (
    SELECT ROW_NUMBER() OVER (ORDER BY [t0].[ID]) AS [ROW_NUMBER], [t0].[ParentID]
    FROM [dbo].[Option] AS [t0]
    ) AS [t1]
LEFT OUTER JOIN [dbo].[Option] AS [t2] ON 1=1 
WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p1 + @p2
ORDER BY [t1].[ROW_NUMBER], [t2].[ID]
-- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [0]
-- @p1: Input Int (Size = 0; Prec = 0; Scale = 0) [0]
-- @p2: Input Int (Size = 0; Prec = 0; Scale = 0) [10]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.30729.1

¡Y aquí es donde ganamos!

WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p1 + @p2