Qual è il Linq a SQL equivalente a TOP o LIMIT / OFFSET?


195

Come faccio a fare questo

Select top 10 Foo from MyTable

in Linq a SQL?

Risposte:


146

In VB:

from m in MyTable
take 10
select m.Foo

Ciò presuppone che MyTable implementa IQueryable. Potrebbe essere necessario accedervi tramite un DataContext o un altro provider.

Presuppone inoltre che Foo sia una colonna in MyTable che viene associata a un nome di proprietà.

Vedi http://blogs.msdn.com/vbteam/archive/2008/01/08/converting-sql-to-linq-part-7-union-top-subqueries-bill-horst.aspx per maggiori dettagli.


127
Questo non funziona in C #, non c'è espressione take. Devi usare il metodo Take ().
Adam Lassek,

10
Tecnicamente, l'interrogatore ha chiesto Linq a SQL, quindi VB è un presupposto praticabile. Detto questo, ALassek, sono un ragazzo # me stesso e preferisco la tua risposta. :-)
David Alpert,

3
Bene, il tuo esempio è stato scritto in C # LINQ ed è per questo che l'ho sottolineato.
Adam Lassek,

3
2 problemi: 1) funziona bene in VB. in C # hai il metodo Take. 2) il take funziona nel client, non in db, quindi se hai un grande set di risultati finiresti per ottenere tutto questo dal client dal db!
Yuki,

8
Apprezzo che abbia qualche anno, ma per quelli che stanno arrivando qui, vale la pena notare che il ".Take (x)" dovrebbe apparire prima di fare un ".Select ()" o ".ToList ()", come il " .Take (x) "sarà incluso nell'SQL generato solo se è prima di enumerare i risultati. Se appare dopo questo, allora sarà fatto una volta che il set di risultati è stato elencato ed è quindi una semplice vecchia istruzione Linq!
Bertie,

248

Usa il metodo Take :

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

In VB LINQ ha un'espressione take:

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

Dalla documentazione:

Take<TSource>enumera sourcee restituisce elementi fino a quando gli countelementi non sono stati resi o sourcenon contiene più elementi. Se countsupera il numero di elementi in source, sourcevengono restituiti tutti gli elementi di .


13
Le piccole differenze in LINQ tra C # e VB sono fastidiose. Perché C # non ha un'espressione take come VB? Sembra una svista. E la mancanza di Sub anonimi da parte di VB rende l'agnas molto meno utile.
Adam Lassek,

Proprio quello che stavo cercando +1
jasonco,

1
+1 Proprio quello di cui avevo bisogno. E FWIW, sembra che solo i dieci dischi siano effettivamente arrivati. In caso contrario, il mio SELECT restituirebbe un'enorme quantità di dati, sufficiente a generare una OutOfMemoryException dopo un doloroso ritardo. Con Take ( quantità gestibile ), nessun ritardo, nessuna eccezione.
Bob Kaufman,

VB ora ha anche un metodo Take (). Ho dovuto usare una variabile per la quantità da prendere e l'espressione non ha funzionato, mentre il metodo ha funzionato.
Dave Johnson,

33

Usa il Take(int n)metodo:

var q = query.Take(10);

25

Anche l'OP ha menzionato l'offset, quindi per es. se desideri ottenere gli articoli da 30 a 60, dovresti:

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

Utilizzare il metodo "Skip" per l'offset.
Utilizzare il metodo "Take" per il limite.


13

@Janei: il mio primo commento qui riguarda il tuo campione;)

Penso che se ti piace in questo modo, vuoi prendere 4, quindi applicare l'ordinamento su questi 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
                };

Diverso dall'ordinare l'intero tbl_News per idNews in ordine decrescente e quindi prendendo 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);

no ? i risultati possono essere diversi.


5

Funziona bene in C #

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

4

Mi piace così:

 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
Il problema con questo approccio è che ne prenderai 4 e poi li ordinerai, quando sospetto che quello che vuoi davvero sia ottenere i primi 4 risultati. Devi fare il take dopo l'ordine, vedi il commento di Yanns.
Russell Troywest,


3

Se il take avviene sul client o nel db dipende da dove si applica l'operatore take. Se lo si applica prima di enumerare la query (ovvero prima di utilizzarla in un foreach o convertirla in una raccolta), il take comporterà l'operatore SQL "n" in alto che verrà inviato al db. Puoi vederlo se esegui il profiler SQL. Se si applica il Take dopo aver enumerato la query, ciò accadrà sul client, poiché LINQ avrà dovuto recuperare i dati dal database per poterlo enumerare attraverso di esso


2

Il rilevamento dei dati di DataBase senza ordinamento è uguale al take casuale


Certamente non è casuale, anche se i risultati non sono garantiti ripetibili, ma ci sono molte volte che vuoi farlo, in particolare durante i test.
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

Ho dovuto usare il metodo Take (n), quindi trasformarmi in elenco, ha funzionato come un incantesimo:

    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

In questo modo ha funzionato per me:

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

Ho appena modificato il tuo post, ho tradotto il testo portoghese in inglese, perché questo sito è solo in inglese (non si applica ai nomi delle variabili, ecco perché non li ho cambiati).
waka,

Scusa ! Non me ne sono reso conto, pensavo di essere nello stackoverflow brasiliano. Siamo spiacenti
Gladson Reis,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.