D'abord, un peu de raisonnement pour le bug Take.
Si vous prenez simplement, le traducteur de requête utilise simplement le haut. Top10 ne donnera pas la bonne réponse si la cardinalité est brisée en rejoignant une collection enfant. Ainsi, le traducteur de requête ne joint pas dans la collection enfant (à la place, il requeries pour les enfants).
Si vous Sauter et Take, le traducteur de requête entre en jeu avec une certaine logique RowNumber sur les lignes parents ... ces rownumbers laisser prendre 10 les parents, même si cela est vraiment 50 dossiers en raison de chaque parent ayant 5 enfants .
Si vous Ignorer (0) et Prendre, Ignorer est supprimé en tant que non-opération par le traducteur - c'est comme si vous n'aviez jamais dit Passer.
Cela va être un saut conceptuel difficile d'où vous êtes (en appelant Skip and Take) à une «solution de contournement simple». Ce que nous devons faire - est de forcer la traduction à se produire à un point où le traducteur ne peut pas supprimer Skip (0) en tant que non-opération. Nous devons appeler Sauter, et fournir le numéro ignoré à un moment ultérieur.
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);
Ceci produit la requête suivante:
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
Et voici où nous gagnons!
WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p1 + @p2
Cela fonctionne mais j'ai dû utiliser IEnumerable au lieu de simplement IEnumerable pour appeler ToList. C'est aussi une demi-seconde plus rapide dans mon test. Bonne réponse. –
JohnOpincar