J'utilise LINQ to SQL (en fait, il est dynamique LINQ to SQL qui vous permet de passer des chaînes à l'exécution des clauses où, orderby etc.) Mais je me certains résultats différents et il semble être basé sur si le T-SQL sous-jacent utilise le mot-clé TOP ou en utilisant BETWEEN.LINQ to SQL fournit des résultats différents lorsque vous utilisez TOP et entre
J'ai essayé de le décomposer le problème dans un petit exemple, voici le scénario:
J'utilise un modèle référentiel et la méthode suivante qui relie simplement 2 tables avec une jointure externe gauche.
public IQueryable<TestGalleryViewModel> FetchGalleryItems()
{
var galleryItems = from painting in Gallery
join artist in Artists
on painting.ArtistID equals artist.ArtistID
into paintingArtists
from artist in paintingArtists.DefaultIfEmpty()
select new TestGalleryViewModel
{
Id = painting.PaintingID,
ArtistName = artist == default(Artist) ? "" : artist.Surname + " " + artist.Forenames,
};
return galleryItems;
}
J'ai alors une petite méthode de test qui utilise la méthode FetchGalleryItems:
var query = respository.Test_FetchGalleryItems().Where("ArtistName.Contains(\"Adams Charles James\")");
var orderedlist = query.OrderBy("ArtistName asc");
var page1 = orderedlist.Skip(0).Take(5);
var page2 = orderedlist.Skip(5).Take(5);
Le orderedList contient les valeurs sous-jacentes suivantes:
176 ADAMS Charles James
620 ADAMS Charles James
621 ADAMS Charles James
660 ADAMS Charles James
683 ADAMS Charles James
707 ADAMS Charles James
735 ADAMS Charles James
739 ADAMS Charles James
740 ADAMS Charles James
741 ADAMS Charles James
Ce qui est ce que j'attendais. Mais page1 contient
707 ADAMS Charles James
683 ADAMS Charles James
660 ADAMS Charles James
621 ADAMS Charles James
620 ADAMS Charles James
qui, comme vous pouvez le voir est PAS les 5 premiers articles. Page2 contient
707 ADAMS Charles James
735 ADAMS Charles James
739 ADAMS Charles James
740 ADAMS Charles James
741 ADAMS Charles James
Whis est ce que j'attendais, il est des articles 6 à 10.
Le T-SQL sous-jacente pour page1 est
SELECT TOP (5) [t3].[PaintingID] AS [Id], [t3].[value] AS [ArtistName]
FROM (
SELECT [t0].[PaintingID],
(CASE
WHEN [t2].[test] IS NULL THEN CONVERT(NVarChar(101),'')
ELSE ([t2].[Surname] + ' ') + [t2].[Forenames]
END) AS [value]
FROM [dbo].[Gallery] AS [t0]
LEFT OUTER JOIN (
SELECT 1 AS [test], [t1].[ArtistID], [t1].[Surname], [t1].[Forenames]
FROM [dbo].[Artists] AS [t1]
) AS [t2] ON [t0].[ArtistID] = ([t2].[ArtistID])
) AS [t3]
WHERE [t3].[value] LIKE '%Adams Charles James%'
ORDER BY [t3].[value]
avis qu'il utilise TOP (5)
Le T-SQL sous-jacente pour page2 est
SELECT [t4].[PaintingID] AS [Id], [t4].[value] AS [ArtistName]
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY [t3].[value], [t3].[Surname], [t3].[Forenames]) AS [ROW_NUMBER], [t3].[PaintingID], [t3].[value]
FROM (
SELECT [t0].[PaintingID],
(CASE
WHEN [t2].[test] IS NULL THEN CONVERT(NVarChar(101),'')
ELSE ([t2].[Surname] + ' ') + [t2].[Forenames]
END) AS [value], [t2].[Surname], [t2].[Forenames]
FROM [dbo].[Gallery] AS [t0]
LEFT OUTER JOIN (
SELECT 1 AS [test], [t1].[ArtistID], [t1].[Surname], [t1].[Forenames]
FROM [dbo].[Artists] AS [t1]
) AS [t2] ON [t0].[ArtistID] = ([t2].[ArtistID])
) AS [t3]
WHERE [t3].[value] LIKE '%Adams Charles James%'
) AS [t4]
WHERE [t4].[ROW_NUMBER] BETWEEN 5 + 1 AND 5 + 5
ORDER BY [t4].[ROW_NUMBER]
avis qu'il utilise ENTRE
Quand je coller les commandes T-SQL dans la gestion SQL Express Studio Je reçois les résultats que je viens de décrire. Si je le T-SQL page2 et modifié la ligne
WHERE [t4].[ROW_NUMBER] BETWEEN 5 + 1 AND 5 + 5
être
WHERE [t4].[ROW_NUMBER] BETWEEN 1 AND 5
-je obtenir les résultats que j'attendais pour page1. c'est-à-dire les 5 premiers articles.
176 ADAMS Charles James
620 ADAMS Charles James
621 ADAMS Charles James
660 ADAMS Charles James
683 ADAMS Charles James
Donc, en un mot lorsque le T-SQL utilise entre au lieu de TOP-je obtenir les résultats que j'attendais.
J'utilise le filtrage (clause where), le tri (orderBy) et la pagination (sauter et prendre) sur mon application et la nécessité de gérer cela assez générique.
- Y at-il un moyen de forcer à utiliser LINQ la ENTRE syntaxe au lieu de TOP?
- Dois-je aborder ce différemment? pour le long post
Toutes mes excuses.
Cordialement, Simon
Notez également que vous avez une clause Order By différente dans la deuxième requête SQL. Essayez d'évaluer var orderedlist = query.OrderBy ("ArtistName asc"). ToList(); d'abord. Et puis obtenir des pages à partir de là. –