Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

LINQ to SQL Take w/o Skip provoca più istruzioni SQL

Primo:qualche ragionamento per il bug Take.

Se semplicemente prendi , il traduttore di query usa semplicemente top. Top10 non darà la risposta giusta se la cardinalità viene interrotta entrando in una raccolta figlio. Quindi il traduttore di query non si unisce alla raccolta figlio (invece richiede per i bambini).

Se Salta e prendi , quindi il traduttore di query si attiva con una logica RowNumber sulle righe principali... questi numeri di riga consentono di richiedere 10 genitori, anche se in realtà si tratta di 50 record poiché ogni genitore ha 5 figli.

Se Salta(0) e prendi , Skip viene rimosso come non operazione dal traduttore, proprio come non hai mai detto Skip.

Questo sarà un duro salto concettuale da dove ti trovi (chiamando Skip and Take) a una "semplice soluzione alternativa". Quello che dobbiamo fare è forzare la traduzione in un punto in cui il traduttore non può rimuovere Skip(0) come non operazione. Dobbiamo chiamare Skip e fornire il numero saltato in un secondo momento.

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);

Questo produce la seguente query:

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

Ed è qui che vinciamo!

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