Quel est le Linq to SQL équivalent à TOP ou LIMIT / OFFSET?


Réponses:


146

En VB:

from m in MyTable
take 10
select m.Foo

Cela suppose que MyTable implémente IQueryable. Vous devrez peut-être y accéder via un DataContext ou un autre fournisseur.

Il suppose également que Foo est une colonne de MyTable qui est mappée sur un nom de propriété.

Voir http://blogs.msdn.com/vbteam/archive/2008/01/08/converting-sql-to-linq-part-7-union-top-subqueries-bill-horst.aspx pour plus de détails.


127
Cela ne fonctionne pas en C #, il n'y a pas d'expression de prise. Vous devez utiliser la méthode Take ().
Adam Lassek

10
Techniquement, l'interrogateur a demandé Linq à SQL, donc VB est une hypothèse viable. Cela dit, ALassek, je suis un gars ac # moi-même et je préfère votre réponse. :-)
David Alpert

3
Eh bien, votre exemple a été écrit en C # LINQ, c'est pourquoi je l'ai souligné.
Adam Lassek

3
2 problèmes: 1) cela fonctionne très bien en VB. en C # vous avez la méthode Take. 2) la prise fonctionne dans le client, pas dans la base de données, donc si vous avez un grand ensemble de résultats, vous finirez par tout obtenir au client à partir de la base de données!
Yuki

8
Appréciez que cela date de quelques années, mais pour ceux qui viennent juste d'arriver, il convient de noter que le ".Take (x)" devrait apparaître avant de faire un ".Select ()" ou ".ToList ()", comme le " .Take (x) "ne sera inclus dans le SQL généré que si c'est avant d'énumérer les résultats. Si cela apparaît après cela, alors cela sera fait une fois que le jeu de résultats aura été énuméré et sera donc une simple vieille instruction Linq!
Bertie

248

Utilisez la méthode Take :

var foo = (from t in MyTable
           select t.Foo).Take(10);

Dans VB LINQ a une expression de prise:

Dim foo = From t in MyTable _
          Take 10 _
          Select t.Foo

De la documentation:

Take<TSource>énumère sourceet renvoie des éléments jusqu'à ce que des countéléments aient été générés ou sourcene contiennent plus d'éléments. Si countdépasse le nombre d'éléments dans source, tous les éléments de sourcesont retournés.


13
Les petites différences de LINQ entre C # et VB sont ennuyeuses. Pourquoi C # n'a-t-il pas une expression de prise comme VB? Cela ressemble à un oubli. Et le manque de VB de Subs anonymes rend les lambdas beaucoup moins utiles.
Adam Lassek

Exactement ce que je cherchais +1
jasonco

1
+1 Juste ce dont j'avais besoin aussi. Et FWIW, il semble que seuls les dix enregistrements descendent en fait. Sinon, mon SELECT retournerait une énorme quantité de données, suffisamment pour lancer une OutOfMemoryException après un délai douloureux. Avec Take ( quantité gérable ), pas de retard, pas d'exception.
Bob Kaufman

VB dispose désormais également d'une méthode Take (). J'ai dû utiliser une variable pour le montant à prendre, et l'expression n'a pas fonctionné, contrairement à la méthode.
Dave Johnson

33

Utilisez la Take(int n)méthode:

var q = query.Take(10);

25

L'OP a également mentionné le décalage, donc par exemple. si vous souhaitez obtenir les articles de 30 à 60, vous feriez:

var foo = (From t In MyTable
       Select t.Foo).Skip(30).Take(30);

Utilisez la méthode "Skip" pour l'offset.
Utilisez la méthode "Take" pour la limite.


13

@Janei: mon premier commentaire ici concerne votre échantillon;)

Je pense que si vous aimez ça, vous voulez prendre 4, puis appliquer le tri sur ces 4.

var dados =  from d in dc.tbl_News.Take(4) 
                orderby d.idNews descending
                select new 
                {
                    d.idNews,
                    d.titleNews,
                    d.textNews,
                    d.dateNews,
                    d.imgNewsThumb
                };

Différent du tri de tbl_News entières par idNews descendant puis prenant 4

var dados =  (from d in dc.tbl_News
                orderby d.idNews descending
                select new 
                {
                    d.idNews,
                    d.titleNews,
                    d.textNews,
                    d.dateNews,
                    d.imgNewsThumb
                }).Take(4);

non ? les résultats peuvent être différents.


5

Cela fonctionne bien en C #

var q = from m in MyTable.Take(10)
        select m.Foo

4

J'aime ça:

 var dados =  from d in dc.tbl_News.Take(4) 
                orderby d.idNews descending

                select new 
                {
                    d.idNews,
                    d.titleNews,
                    d.textNews,
                    d.dateNews,
                    d.imgNewsThumb
                };

7
Le problème avec cette approche est que vous en prendrez 4, puis les commanderez, alors que je soupçonne que ce que vous voulez vraiment, c'est obtenir les 4 meilleurs résultats. Vous devez faire la prise après la commande, voir le commentaire de Yanns.
Russell Troywest


3

Que la prise ait lieu sur le client ou dans la base de données dépend de l'endroit où vous appliquez l'opérateur de prise. Si vous l'appliquez avant d'énumérer la requête (c'est-à-dire avant de l'utiliser dans un foreach ou de le convertir en une collection), la prise entraînera l'envoi de l'opérateur SQL "top n" à la base de données. Vous pouvez le voir si vous exécutez le profileur SQL. Si vous appliquez la prise après avoir énuméré la requête, cela se produira sur le client, car LINQ aura dû récupérer les données de la base de données pour que vous puissiez les énumérer à travers celle-ci.


2

La prise de données de DataBase sans tri est identique à la prise aléatoire


Ce n'est certainement pas aléatoire, bien que les résultats ne soient pas garantis d'être reproductibles, mais il y a de nombreuses fois que vous voulez le faire, en particulier dans les tests.
Auspex

2
Array oList = ((from m in dc.Reviews
                           join n in dc.Users on m.authorID equals n.userID
                           orderby m.createdDate descending
                           where m.foodID == _id                      
                           select new
                           {
                               authorID = m.authorID,
                               createdDate = m.createdDate,
                               review = m.review1,
                               author = n.username,
                               profileImgUrl = n.profileImgUrl
                           }).Take(2)).ToArray();

0

J'ai dû utiliser la méthode Take (n), puis transformer en liste, fonctionnait comme un charme:

    var listTest = (from x in table1
                     join y in table2
                     on x.field1 equals y.field1
                     orderby x.id descending
                     select new tempList()
                     {
                         field1 = y.field1,
                         active = x.active
                     }).Take(10).ToList();

0

De cette façon, cela a fonctionné pour moi:

var noticias = from n in db.Noticias.Take(6)
                       where n.Atv == 1
                       orderby n.DatHorLan descending
                       select n;

Je viens de modifier votre article, j'ai traduit le texte portugais en anglais, car ce site est uniquement en anglais (ne s'applique pas aux noms de variables, c'est pourquoi je ne les ai pas modifiés).
waka

Désolé ! Je ne m'en rendais pas compte, je pensais que j'étais dans le stackoverflow brésilien. Désolé
Gladson Reis

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.