Je suis juste curieux de savoir comment Skip & Take est censé fonctionner. J'obtiens les résultats que je veux voir du côté client, mais lorsque je connecte le profileur SQL d'AnjLab et que je regarde le SQL qui est exécuté, il semble qu'il demande et renvoie l'ensemble des lignes au client.
Est-il vraiment possible de renvoyer toutes les lignes, puis de les trier et de les réduire avec LINQ du côté client ?
J'ai essayé de le faire avec Entity Framework et Linq to SQL ; les deux semblent avoir le même comportement.
Je ne suis pas sûr que cela fasse une différence, mais j'utilise C# dans VWD 2010.
Une idée ?
public IEnumerable<Store> ListStores(Func<Store, string> sort, bool desc, int page, int pageSize, out int totalRecords)
{
var context = new TectonicEntities();
totalRecords = context.Stores.Count();
int skipRows = (page - 1) * pageSize;
if (desc)
return context.Stores.OrderByDescending(sort).Skip(skipRows).Take(pageSize).ToList();
return context.Stores.OrderBy(sort).Skip(skipRows).Take(pageSize).ToList();
}
SQL résultant (Note : J'exclue la requête Count) :
SELECT
[Extent1].[ID] AS [ID],
[Extent1].[Name] AS [Name],
[Extent1].[LegalName] AS [LegalName],
[Extent1].[YearEstablished] AS [YearEstablished],
[Extent1].[DiskPath] AS [DiskPath],
[Extent1].[URL] AS [URL],
[Extent1].[SecureURL] AS [SecureURL],
[Extent1].[UseSSL] AS [UseSSL]
FROM [dbo].[tec_Stores] AS [Extent1]
Après quelques recherches plus approfondies, j'ai découvert que le système suivant fonctionne comme je l'attendais :
public IEnumerable<Store> ListStores(Func<Store, string> sort, bool desc, int page, int pageSize, out int totalRecords)
{
var context = new TectonicEntities();
totalRecords = context.Stores.Count();
int skipRows = (page - 1) * pageSize;
var qry = from s in context.Stores orderby s.Name ascending select s;
return qry.Skip(skipRows).Take(pageSize);
}
SQL résultant :
SELECT TOP (3)
[Extent1].[ID] AS [ID],
[Extent1].[Name] AS [Name],
[Extent1].[LegalName] AS [LegalName],
[Extent1].[YearEstablished] AS [YearEstablished],
[Extent1].[DiskPath] AS [DiskPath],
[Extent1].[URL] AS [URL],
[Extent1].[SecureURL] AS [SecureURL],
[Extent1].[UseSSL] AS [UseSSL]
FROM ( SELECT [Extent1].[ID] AS [ID], [Extent1].[Name] AS [Name], [Extent1].[LegalName] AS [LegalName], [Extent1].[YearEstablished] AS [YearEstablished], [Extent1].[DiskPath] AS [DiskPath], [Extent1].[URL] AS [URL], [Extent1].[SecureURL] AS [SecureURL], [Extent1].[UseSSL] AS [UseSSL], row_number() OVER (ORDER BY [Extent1].[Name] ASC) AS [row_number]
FROM [dbo].[tec_Stores] AS [Extent1]
) AS [Extent1]
WHERE [Extent1].[row_number] > 3
ORDER BY [Extent1].[Name] ASC
J'aime vraiment la façon dont la première option fonctionne ; Passer dans une expression lambda pour le tri. Existe-t-il un moyen d'accomplir la même chose avec la syntaxe orderby de LINQ to SQL ? J'ai essayé d'utiliser qry.OrderBy(sort).Skip(skipRows).Take(pageSize), mais cela a fini par me donner les mêmes résultats que mon premier bloc de code. Cela m'amène à penser que mes problèmes sont liés d'une manière ou d'une autre à OrderBy.
\====================================
PROBLÈME RÉSOLU
J'ai dû envelopper la fonction lambda entrante dans Expression :
Expression<Func<Store,string>> sort
0 votes
Pouvez-vous nous donner le code de la fonction de tri ?
0 votes
Bien sûr, je passe juste un lambda. Exemples : x => x.Name, x => x.LegalName, x => x.YearEstablished.ToString()
0 votes
Je commence à penser que je devrais simplement passer une chaîne de caractères puis utiliser une instruction switch pour définir le paramètre orderby approprié pour la requête LINQ :( La première méthode était tellement plus cool et impliquait beaucoup moins de code. Je n'arrive pas à comprendre pourquoi elle ne fonctionne pas correctement. Sans savoir exactement ce qui se passe, il semble que .OrderBy et .OrderByDescending déclenchent une récupération de la base de données, puis appliquent le tri, puis sautent et prennent. Peut-être que c'est ça, cependant... peut-être que OrderBy ne sait pas comment convertir x => x.Name dans le SQL approprié et qu'il récupère le jeu de résultats puis applique le tri et le filtrage.