Entity Framework 4 Single () vs First () vs FirstOrDefault ()

119

Ich habe eine teuflische Zeit damit, einen Vergleich der verschiedenen Möglichkeiten zu finden, nach einem einzelnen Element zu fragen und wann jedes verwendet werden soll.

Hat jemand einen Link, der all dies vergleicht, oder eine kurze Erklärung, warum Sie einen über den anderen verwenden würden? Gibt es noch mehr Betreiber, die mir nicht bekannt sind?

Danke dir.

asfsadf
quelle

Antworten:

205

Hier ist eine Übersicht über die verschiedenen Methoden:

  • Find () - wenn Sie einen Artikel per Primärschlüssel erhalten möchten. Dies gibt null zurück, wenn kein Element gefunden werden kann. Es wird im Kontext angezeigt, bevor Sie zur Datenbank gehen (wie von Yaron in den Kommentaren hervorgehoben). Dies kann ein wichtiger Effizienzfaktor sein, wenn Sie dieselbe Entität mehrmals abrufen müssen, während derselbe Kontext aktiv ist.

  • Single () - wenn Sie erwarten, dass genau ein Element von einer Abfrage zurückgegeben wird. Dies löst eine Ausnahme aus, wenn die Abfrage nicht genau ein Element zurückgibt.

  • SingleOrDefault () - Wenn Sie erwarten, dass von einer Abfrage null oder ein Element zurückgegeben wird (dh Sie sind nicht sicher, ob ein Element mit einem bestimmten Schlüssel vorhanden ist). Dies löst eine Ausnahme aus, wenn die Abfrage keine null oder eins Elemente zurückgibt.

  • First () - Wenn Sie erwarten, dass ein oder mehrere Elemente von einer Abfrage zurückgegeben werden, Sie jedoch nur auf das erste Element in Ihrem Code zugreifen möchten (die Reihenfolge kann in der Abfrage hier wichtig sein). Dies löst eine Ausnahme aus, wenn die Abfrage nicht mindestens ein Element zurückgibt.

  • FirstOrDefault () - Wenn Sie erwarten, dass null oder mehr Elemente von einer Abfrage zurückgegeben werden, Sie aber nur auf das erste Element in Ihrem Code zugreifen möchten (dh Sie sind nicht sicher, ob ein Element mit einem bestimmten Schlüssel vorhanden ist).

Steve Willcock
quelle
1
Das hängt vom Szenario ab. Wenn Sie wissen, dass Sie für eine bestimmte Abfrage immer einen einzelnen Datensatz von der Datenbank zurückerhalten sollten, nicht mehr und nicht weniger, dann ist Single () der richtige. In anderen Situationen können die anderen angemessener sein. In früheren Versionen von EF waren wir auf First () und FirstOrDefault () beschränkt, die für Szenarien funktionieren, in denen Sie einen einzelnen Datensatz erwarten, Sie jedoch nicht warnen, wenn Sie tatsächlich mehr als diesen einzelnen Datensatz zurückerhalten, was abhängig davon wichtig sein kann die Situation.
Steve Willcock
1
Vielen Dank. Ich kann mir nicht mehr vorstellen, First () zu brauchen, wo Single () nicht besser wäre. Wenn ich weniger dicht wäre, könnte ich sicher verstehen, wann ich First () noch verwenden soll.
Asfsadf
1
First () ist am sinnvollsten, wenn Sie nur das Objekt mit dem höchsten oder niedrigsten Wert abrufen möchten, nach dem Sie bestellen. Finden Sie mir zum Beispiel den Verkauf mit dem höchsten Gesamtwert. Sales.OrderByDescending(s => s.TotalValue).First();
Mike Chamberlain
5
Alle Kommentare sehen einen wichtigen Unterschied aus. Find () ist die einzige Methode, die den Kontext durchsucht, bevor die Datenbank aufgerufen wird.
Yaron Levi
5
Ein weiterer Punkt ist , wenn eine SQL - Datenbank abfragen, Singleoder SingleOrDefaultfür 2 Datensätze (Limit 2) , während abfragen Firstoder FirstOrDefaultwird abfrage 1 (Limit 1).
Bart Calixto
22

Ich neige immer dazu, zu benutzen FirstOrDefault. Wenn Sie wirklich wählerisch mit der Leistung sein möchten, sollten Sie FirstOrDefaultin EF verwenden. Unter dem Deckmantel SingleOrDefaultwird top (2) in der Abfrage verwendet, da geprüft werden muss, ob eine zweite Zeile vorhanden ist, die den Kriterien entspricht, und in diesem Fall eine Ausnahme ausgelöst wird. Grundsätzlich SingleOrDefaultsagen Sie, dass Sie eine Ausnahme auslösen möchten, wenn Ihre Abfrage mehr als 1 Datensatz zurückgibt.

zeeshanhirani
quelle
5
Haben Sie jemals den Leistungsunterschied zwischen FirstOrDefaultund gemessen SingleOrDefault, um signifikant zu sein? Ich würde sagen, es ist in den meisten Fällen eine vorzeitige Optimierung.
Steven
Ich neige dazu, Single()oder SingleOrDefault()wenn ich etwas zurückgebe, von dem es nur eines geben sollte . Der Grund, warum ich dies tue, besteht darin, Fehler zu erkennen, indem schlecht geschriebene Abfragen, die mehr zurückgeben als sie sollten, fehlschlagen. Zumindest in meinen Augen wird dies dazu beitragen, die Daten im System konsistent zu halten. Natürlich ist das langsamer, aber ich würde vermuten, dass es nicht viel langsamer ist, und ich bin bereit, diesen Preis zu zahlen.
Mortb
15

Es ist wirklich sehr einfach: SingleGibt einen einzelnen Artikel zurück und löst eine Ausnahme aus, wenn entweder keiner oder mehr als ein Artikel vorhanden ist. Firstgibt den ersten Gegenstand zurück oder wirft, wenn kein Gegenstand vorhanden ist. FirstOrDefaultGibt das erste Element zurück oder gibt den Standardwert zurück ( nullfalls der angegebene Typ ein Referenztyp ist), wenn kein Element vorhanden ist.

Dies ist das Verhalten, das die API haben soll. Beachten Sie jedoch, dass die zugrunde liegende Implementierung ein anderes Verhalten aufweisen kann. Während Entity Framework dies befolgt, kann ein O / RM wie LLBLGen auch nullbeim Aufrufen zurückkehren , Firstwas eine sehr seltsame Sache ist. Dies war eine sehr seltsame (und hartnäckige) Entscheidung des Designers IMO.

Steven
quelle
Danke Steven. Ich frage mich wohl immer noch, warum Sie eins über das andere verwenden würden. Ich habe immer FirstOrDefault () verwendet und war neugierig, warum viele der neuen Beispiele, die ich gesehen habe, auf Single () umgestellt wurden. Gibt es einen Grund, zu Single () zu wechseln? Gibt es andere, die das Gleiche erreichen, was ich stattdessen in Betracht ziehen sollte?
Asfsadf
7
Wenn Sie möchten, dass Ihr Code "schnell ausfällt", lassen Sie First () und Single () Ihren Code genauer sagen, was erwartet wird (damit er sonst fehlschlagen kann)
Frank Schwieterman
3
Ich stimme Frank voll und ganz zu. Es geht auch darum, Absichten zu kommunizieren. Singledrückt deutlich aus, dass Sie nur ein Element erwarten.
Steven
8

Die vier Methoden haben jeweils ihren Platz; Obwohl Sie wirklich nur zwei verschiedene Operationen haben.

  • Erstens - Wenn Sie eine Ergebnismenge erwarten, die mehrere Elemente enthält, geben Sie mir das erste Element in dieser Gruppe.
  • Single - Wenn Sie ein einzelnes Ergebnis erwarten, geben Sie mir diesen Artikel.

Die xxxxOrDefault () -Version fügt nur hinzu: "Ich möchte eine leere Ergebnismenge nicht als außergewöhnlichen Umstand betrachten."

Chris Shaffer
quelle
OK, also scheint es mir, dass First () selten nützlich sein würde. Es fällt mir schwer, ein Szenario zu finden, in dem Single () nicht die erste Option wäre. Sie haben zufällig eine schnelle Hand? Vielen Dank.
Asfsadf
3
Leider verwenden viele Entwickler First () oder FirstOrDefault () nur als Abwehrmaßnahme, da sie glauben, dass eine Ausnahme vermieden wird, wenn sie wirklich nur das Potenzial hat, echte Probleme zu verbergen.
Matt H
3

Auf der anderen Seite können Sie diese Methoden wie folgt durch die Kernlogik teilen:

  • Die Methode fragt die Datenbank direkt ab : Single (), SingleOrDefault (), First (), FirstOrDefault ()
  • Die Methode führt eine Suche im Cache durch, bevor die Abfrage für die Datenbank ausgegeben wird : Find ()

Für einige Leistungsdetails, vor allem im zweiten Fall können Sie hier sehen: https://msdn.microsoft.com/en-us/data/hh949853.aspx?f=255&MSPPError=-2147217396#3

Darüber hinaus können Sie in der ersten Gruppe komplexe Abfragen definieren. Mit der Find () -Methode können Sie jedoch nur den Entitätsschlüssel für die Suche bereitstellen.

Kryszal
quelle
0

Single () und SingleOrDefault () werden normalerweise für eindeutige Bezeichner wie IDs verwendet, während First () oder FirstOrDefault () normalerweise für eine Abfrage verwendet werden, die mehrere Ergebnisse haben kann, aber nur die "Top 1" möchten .

Single () oder First () würden eine Ausnahme auslösen, wenn kein Ergebnis zurückgegeben wird. SingleOrDefault () und FirstOrDefault () fangen die Ausnahme ab und geben null oder default (ResultDataType) zurück.

MilkTea027
quelle