Was entspricht Linq to SQL TOP oder LIMIT / OFFSET?

195

Wie mache ich das

Select top 10 Foo from MyTable

in Linq zu SQL?

Herb Caudill
quelle

Antworten:

146

In VB:

from m in MyTable
take 10
select m.Foo

Dies setzt voraus, dass MyTable IQueryable implementiert. Möglicherweise müssen Sie über einen DataContext oder einen anderen Anbieter darauf zugreifen.

Es wird auch davon ausgegangen, dass Foo eine Spalte in MyTable ist, die einem Eigenschaftsnamen zugeordnet wird.

Weitere Informationen finden Sie unter http://blogs.msdn.com/vbteam/archive/2008/01/08/converting-sql-to-linq-part-7-union-top-subqueries-bill-horst.aspx .

David Alpert
quelle
127
Das funktioniert in C # nicht, es gibt keinen Take-Ausdruck. Sie müssen die Take () -Methode verwenden.
Adam Lassek
10
Technisch gesehen hat der Fragesteller nach Linq to SQL gefragt, daher ist VB eine tragfähige Annahme. Das heißt, ALassek, ich bin selbst ein Typ und bevorzuge deine Antwort. :-)
David Alpert
3
Nun, Ihr Beispiel wurde in C # LINQ geschrieben, weshalb ich darauf hingewiesen habe.
Adam Lassek
3
2 Probleme: 1) Dies funktioniert gut in VB. In C # haben Sie die Take-Methode. 2) Die Aufnahme funktioniert im Client, nicht in der Datenbank. Wenn Sie also eine große Ergebnismenge haben, erhalten Sie am Ende alles von der Datenbank zum Client!
Yuki
8
Schätzen Sie, dass dies ein paar Jahre alt ist, aber für diejenigen, die gerade erst hierher kommen, ist es erwähnenswert, dass ".Take (x)" angezeigt werden sollte, bevor Sie ".Select ()" oder ".ToList ()" als ". .Take (x) "wird nur dann in die generierte SQL aufgenommen, wenn Sie die Ergebnisse aufgelistet haben. Wenn es danach erscheint, wird es durchgeführt, sobald die Ergebnismenge aufgezählt wurde und daher eine einfache alte Linq-Anweisung ist!
Bertie
248

Verwenden Sie die Take-Methode :

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

In VB hat LINQ einen Take-Ausdruck:

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

Aus der Dokumentation:

Take<TSource>zählt sourceElemente auf und ergibt sie, bis countElemente ergeben wurden oder sourcekeine Elemente mehr enthalten. Wenn countdie Anzahl der Elemente in überschritten wird source, werden alle Elemente von sourcezurückgegeben.

Adam Lassek
quelle
13
Die kleinen Unterschiede im LINQ zwischen C # und VB sind ärgerlich. Warum hat C # keinen Take-Ausdruck wie VB? Das scheint ein Versehen zu sein. Und das Fehlen anonymer Subs von VB macht Lambdas viel weniger nützlich.
Adam Lassek
Genau das, wonach ich gesucht habe +1
jasonco
1
+1 Genau das, was ich auch brauchte. Und FWIW scheint, dass nur die zehn Platten tatsächlich in die Pfeife kommen. Mein SELECT würde andernfalls eine enorme Datenmenge zurückgeben, die ausreicht, um nach einer schmerzhaften Verzögerung eine OutOfMemoryException auszulösen . Mit Take ( überschaubare Menge ) keine Verzögerung, keine Ausnahme.
Bob Kaufman
VB hat jetzt auch eine Take () -Methode. Ich musste eine Variable für den Betrag verwenden, und der Ausdruck funktionierte nicht, während die Methode dies tat.
Dave Johnson
33

Verwenden Sie die Take(int n)Methode:

var q = query.Take(10);
Amcoder
quelle
24

Das OP erwähnte tatsächlich auch den Versatz, also zum Beispiel. Wenn Sie die Artikel von 30 bis 60 erhalten möchten, würden Sie Folgendes tun:

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

Verwenden Sie die Methode "Überspringen" für den Versatz.
Verwenden Sie die "Take" -Methode als Limit.

Inc33
quelle
13

@ Janei: Mein erster Kommentar hier ist über deine Probe;)

Ich denke, wenn dir das gefällt, möchtest du 4 nehmen und dann die Sortierung auf diese 4 anwenden.

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
                };

Anders als das Sortieren ganzer tbl_News nach absteigenden idNews und anschließendem Nehmen von 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);

Nein ? Ergebnisse können unterschiedlich sein.

Yann
quelle
5

Dies funktioniert gut in C #

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

Ich mag das:

 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
quelle
7
Das Problem bei diesem Ansatz ist, dass Sie 4 nehmen und sie dann bestellen, wenn ich vermute, dass Sie wirklich die besten 4 Ergebnisse erzielen möchten. Sie müssen die Aufnahme nach der Bestellung machen, siehe Yanns Kommentar.
Russell Troywest
3

Sie würden die Take (N) -Methode verwenden.

FlySwat
quelle
3

Ob der Take auf dem Client oder in der Datenbank stattfindet, hängt davon ab, wo Sie den Take-Operator anwenden. Wenn Sie es anwenden, bevor Sie die Abfrage aufzählen (dh bevor Sie es in einem foreach verwenden oder in eine Sammlung konvertieren), führt der Take dazu, dass der SQL-Operator "top n" an die Datenbank gesendet wird. Sie können dies sehen, wenn Sie den SQL-Profiler ausführen. Wenn Sie den Take nach dem Auflisten der Abfrage anwenden, geschieht dies auf dem Client, da LINQ die Daten aus der Datenbank abrufen musste, damit Sie sie auflisten können

user124368
quelle
2

Das Aufnehmen von Daten aus der Datenbank ohne Sortieren entspricht dem zufälligen Aufnehmen

Anton
quelle
Es ist sicherlich nicht zufällig, obwohl die Ergebnisse nicht garantiert wiederholbar sind, aber es gibt viele Fälle, in denen Sie dies tun möchten, insbesondere beim Testen.
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
quelle
0

Ich musste die Take (n) -Methode verwenden und dann in eine Liste umwandeln. Arbeitete wie ein Zauber:

    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();
Apollo-SOFTWARE
quelle
0

So hat es bei mir funktioniert:

var noticias = from n in db.Noticias.Take(6)
                       where n.Atv == 1
                       orderby n.DatHorLan descending
                       select n;
Gladson Reis
quelle
Ich habe gerade Ihren Beitrag bearbeitet und den portugiesischen Text ins Englische übersetzt, da diese Seite nur in englischer Sprache verfasst ist (gilt nicht für Variablennamen, deshalb habe ich diese nicht geändert).
Waka
Es tut uns leid ! Ich wusste nicht, ich dachte, ich wäre im brasilianischen Stackoverflow. Entschuldigung
Gladson Reis
0

Zur limit 1Verwendung von Methoden FirstOrDefault()oder First().

Beispiel

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

Entwickler Marius Žilėnas
quelle