Primero: algún razonamiento para el error Take.
Si acaba de tomar, el traductor de consultas simplemente utiliza la parte superior. Top10 no dará la respuesta correcta si la cardinalidad se rompe uniéndose a una colección de niños. Por lo tanto, el traductor de consultas no se une a la colección secundaria (en cambio, se vuelve a consultar para los hijos).
Si Skip y Take, entonces el traductor consulta entra en acción con cierta lógica RowNumber sobre las filas primarias ... estos rownumbers dejar que tome 10 padres, incluso si eso es realmente 50 registros debido a cada padre que tiene 5 hijos .
Si Salta (0) y toma, el traductor omite Omitir como no operado, es como si nunca hubiera dicho Omitir.
Esto va a ser un salto conceptual duro desde donde se encuentra (llamando a Skip y Take) a una "solución simple". Lo que tenemos que hacer es forzar la traducción para que ocurra en un punto donde el traductor no puede eliminar el Omitir (0) como una falta de operación. Necesitamos llamar a Skip y suministrar 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
Esto funciona pero tuve que usar IEnumerable en lugar de solo IEnumerable para llamar a ToList. También es medio segundo más rápido en mi caso de prueba. Buena respuesta. –
JohnOpincar