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

195

Comment puis-je faire cela

Select top 10 Foo from MyTable

de Linq à SQL?

Herbe Caudill
la source

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.

David Alpert
la source
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.

Adam Lassek
la source
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);
amcoder
la source
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.

Inc33
la source
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.

Yann
la source
5

Cela fonctionne bien en C #

var q = from m in MyTable.Take(10)
        select m.Foo
spdrcr911
la source
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
                };
Janei Vieira
la source
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

Vous utiliseriez la méthode Take (N).

FlySwat
la source
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.

user124368
la source
2

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

Anton
la source
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();
minhnguyen
la source
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();
LOGICIEL Apollo
la source
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;
Gladson Reis
la source
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
0

Pour limit 1les méthodes d'utilisation FirstOrDefault()ou First().

Exemple

var y = (from x in q select x).FirstOrDefault();

Développeur Marius Žilėnas
la source