Betrachten Sie die IEnumerable-Erweiterungsmethoden SingleOrDefault()
undFirstOrDefault()
MSDN dokumentiert, dassSingleOrDefault
:
Gibt das einzige Element einer Sequenz oder einen Standardwert zurück, wenn die Sequenz leer ist. Diese Methode löst eine Ausnahme aus, wenn die Sequenz mehr als ein Element enthält.
wohingegen FirstOrDefault
von MSDN (vermutlich , wenn eine Verwendung OrderBy()
oder OrderByDescending()
überhaupt nicht oder keine),
Gibt das erste Element einer Sequenz zurück
Betrachten Sie eine Handvoll Beispielabfragen. Es ist nicht immer klar, wann diese beiden Methoden verwendet werden sollen:
var someCust = db.Customers
.SingleOrDefault(c=>c.ID == 5); //unlikely(?) to be more than one, but technically COULD BE
var bobbyCust = db.Customers
.FirstOrDefault(c=>c.FirstName == "Bobby"); //clearly could be one or many, so use First?
var latestCust = db.Customers
.OrderByDescending(x=> x.CreatedOn)
.FirstOrDefault();//Single or First, or does it matter?
Frage
Welche Konventionen befolgen oder schlagen Sie bei der Entscheidung für die Verwendung SingleOrDefault()
und FirstOrDefault()
in Ihren LINQ-Abfragen vor?
quelle
Wenn Ihre Ergebnismenge 0 Datensätze zurückgibt:
SingleOrDefault
Gibt den Standardwert für den Typ zurück (z. B. ist der Standardwert für int 0).FirstOrDefault
Gibt den Standardwert für den Typ zurückWenn Ihre Ergebnismenge 1 Datensatz zurückgibt:
SingleOrDefault
gibt diesen Datensatz zurückFirstOrDefault
gibt diesen Datensatz zurückWenn Ihre Ergebnismenge viele Datensätze zurückgibt:
SingleOrDefault
löst eine Ausnahme ausFirstOrDefault
gibt den ersten Datensatz zurückFazit:
Wenn eine Ausnahme ausgelöst werden soll, wenn die Ergebnismenge viele Datensätze enthält, verwenden Sie
SingleOrDefault
.Wenn Sie immer 1 Datensatz möchten, unabhängig davon, was die Ergebnismenge enthält, verwenden Sie
FirstOrDefault
quelle
FirstOrDefault
wird der erste Datensatz zurückgegeben bedeutet neuer Datensatz (letzter) / alter Datensatz (erster)? Kannst du mich klären?Es gibt
zwischen den beiden.
Semantischer Unterschied:
FirstOrDefault
Gibt ein erstes Element von möglicherweise mehreren zurück (oder Standard, wenn keines vorhanden ist).SingleOrDefault
geht davon aus, dass es ein einzelnes Element gibt, und gibt es zurück (oder standardmäßig, wenn keines vorhanden ist). Mehrere Artikel stellen eine Vertragsverletzung dar, eine Ausnahme wird ausgelöst.Leistungsunterschied
FirstOrDefault
ist normalerweise schneller, es iteriert, bis es das Element findet und muss nur die gesamte Aufzählung iterieren, wenn es es nicht findet. In vielen Fällen besteht eine hohe Wahrscheinlichkeit, einen Artikel zu finden.SingleOrDefault
muss prüfen, ob es nur ein Element gibt und iteriert daher immer die gesamte Aufzählung. Um genau zu sein, iteriert es, bis es ein zweites Element findet und eine Ausnahme auslöst. In den meisten Fällen gibt es jedoch kein zweites Element.Fazit
Verwenden
FirstOrDefault
Sie diese Option, wenn es Ihnen egal ist, wie viele Artikel vorhanden sind oder wenn Sie es sich nicht leisten können, die Eindeutigkeit zu überprüfen (z. B. in einer sehr großen Sammlung). Wenn Sie beim Hinzufügen der Elemente zur Sammlung die Eindeutigkeit überprüfen, ist es möglicherweise zu teuer, sie bei der Suche nach diesen Elementen erneut zu überprüfen.Verwenden
SingleOrDefault
Sie diese Option, wenn Sie sich nicht zu sehr um die Leistung kümmern müssen und sicherstellen möchten, dass die Annahme eines einzelnen Elements für den Leser klar ist und zur Laufzeit überprüft wird.In der Praxis verwenden Sie
First
/FirstOrDefault
häufig sogar in Fällen, in denen Sie ein einzelnes Element annehmen, um die Leistung zu verbessern. Sie sollten sich immer noch daran erinnern, dassSingle
/SingleOrDefault
die Lesbarkeit (weil es die Annahme eines einzelnen Elements angibt) und die Stabilität (weil es es überprüft) verbessern und es angemessen verwenden kann.quelle
SingleOrDefault
bei der Verwendung von Linq to Objects viele Objekte durchlaufen werden, muss aber nichtSingleOrDefault
höchstens zwei Elemente durchlaufen, wenn Linq beispielsweise mit einer Datenbank spricht. Ich frage mich nur ..Enumerable
.Niemand hat erwähnt, dass FirstOrDefault, das in SQL übersetzt wurde, TOP 1-Datensätze und SingleOrDefault TOP 2-Datensätze ausführt, da bekannt sein muss, dass mehr als 1 Datensatz vorhanden ist.
quelle
FirstOrDefault()
hinzu,LIMIT 0,1
währendSingleOrDefault()
nichts hinzugefügt wird .Für LINQ -> SQL:
SingleOrDefault
FirstOrDefault
quelle
Ich verwende
SingleOrDefault
in Situationen, in denen meine Logik vorschreibt, dass das Ergebnis entweder Null oder Eins ist. Wenn es mehr gibt, ist es eine Fehlersituation, die hilfreich ist.quelle
SingleOrDefault: Sie sagen, dass "höchstens" ein Element mit der Abfrage oder dem Standard übereinstimmt. FirstOrDefault: Sie sagen, dass "mindestens" ein Element mit der Abfrage oder dem Standard übereinstimmt
Sagen Sie das laut, wenn Sie das nächste Mal wählen müssen, und Sie werden wahrscheinlich mit Bedacht wählen. :) :)
quelle
FirstOrDefault. More correctly:
FirstOrDefault` = Beliebig viele Ergebnisse, aber ich kümmere mich nur um das erste, möglicherweise gibt es auch keine Ergebnisse.SingleOrDefault
= Es gibt 1 oder 0 Ergebnisse. Wenn mehr vorhanden sind, liegt irgendwo ein Fehler vor.First
= Es gibt mindestens ein Ergebnis, und ich möchte es.Single
= Es gibt genau 1 Ergebnis, nicht mehr und nicht weniger, und ich möchte dieses.In Ihren Fällen würde ich Folgendes verwenden:
Auswahl nach ID == 5: Es ist in Ordnung, SingleOrDefault hier zu verwenden, da Sie eine [oder keine] Entität erwarten. Wenn Sie mehr als eine Entität mit ID 5 haben, stimmt etwas nicht und ist definitiv eine Ausnahme wert.
Wenn Sie nach Personen suchen, deren Vorname gleich "Bobby" ist, kann es mehrere geben (möglicherweise würde ich denken). Sie sollten also weder Single noch First verwenden. Wählen Sie einfach mit der Where-Operation aus (wenn "Bobby" zu viele zurückgibt Entitäten muss der Benutzer seine Suche verfeinern oder eines der zurückgegebenen Ergebnisse auswählen.
Die Reihenfolge nach Erstellungsdatum sollte auch mit einer Where-Operation ausgeführt werden (es ist unwahrscheinlich, dass nur eine Entität vorhanden ist, die Sortierung ist nicht von großem Nutzen.). Dies bedeutet jedoch, dass ALLE Entitäten sortiert werden sollen. Wenn Sie nur EINE möchten, verwenden Sie FirstOrDefault. Single würde jedes Mal werfen, wenn Sie mehr als eine Entität haben.
quelle
Beide sind die Elementoperatoren und werden verwendet, um ein einzelnes Element aus einer Sequenz auszuwählen. Aber es gibt einen kleinen Unterschied zwischen ihnen. Der Operator SingleOrDefault () würde eine Ausnahme auslösen, wenn mehr als ein Element die Bedingung erfüllt, dass FirstOrDefault () keine Ausnahme für dasselbe auslöst. Hier ist das Beispiel.
quelle
In Ihrem letzten Beispiel:
Ja tut es. Wenn Sie versuchen zu verwenden
SingleOrDefault()
und die Abfrage zu mehr als einem Datensatz führt, erhalten Sie eine Ausnahme. Die einzige Zeit, die Sie sicher verwenden können,SingleOrDefault()
ist, wenn Sie nur 1 und nur 1 Ergebnis erwarten ...quelle
So wie ich es jetzt verstehe,
SingleOrDefault
ist es gut, wenn Sie nach Daten fragen, die garantiert eindeutig sind, dh durch DB-Einschränkungen wie den Primärschlüssel erzwungen werden.Oder gibt es eine bessere Möglichkeit, den Primärschlüssel abzufragen?
Vorausgesetzt mein TableAcc hat
und ich möchte nach einem fragen
AccountNumber 987654
, den ich benutzequelle
Meiner Meinung nach
FirstOrDefault
wird viel überbeansprucht. In den meisten Fällen, in denen Sie Daten filtern, erwarten Sie entweder eine Sammlung von Elementen, die der logischen Bedingung entsprechen, oder ein einzelnes eindeutiges Element anhand seiner eindeutigen Kennung - wie z. B. ein Benutzer, ein Buch, ein Beitrag usw. Warum können wir sogar sagen, dass diesFirstOrDefault()
ein Codegeruch ist, nicht weil etwas nicht stimmt, sondern weil er viel zu oft verwendet wird. Dieser Blog-Beitrag befasst sich ausführlich mit dem Thema. IMO ist meistensSingleOrDefault()
eine viel bessere Alternative. Achten Sie also auf diesen Fehler und stellen Sie sicher, dass Sie die am besten geeignete Methode verwenden, die Ihren Vertrag und Ihre Erwartungen klar darstellt.quelle
Eine Sache, die in den Antworten übersehen wird ....
Wenn es mehrere Ergebnisse gibt, kann FirstOrDefault ohne eine Bestellung von unterschiedliche Ergebnisse zurückbringen, je nachdem, welche Indexstrategie gerade vom Server verwendet wurde.
Persönlich kann ich es nicht ertragen, FirstOrDefault im Code zu sehen, weil es mir sagt, dass der Entwickler sich nicht um die Ergebnisse gekümmert hat. Bei einer Bestellung von kann dies jedoch hilfreich sein, um die neuesten / frühesten zu erzwingen. Ich musste viele Probleme beheben, die von unachtsamen Entwicklern mit FirstOrDefault verursacht wurden.
quelle
Ich habe Google nach der Verwendung der verschiedenen Methoden auf GitHub gefragt. Dazu wird für jede Methode eine Google-Suchabfrage ausgeführt und die Abfrage mithilfe der Abfrage "site: github.com file: cs ..." auf die Domain github.com und die Dateierweiterung .cs beschränkt.
Es scheint, dass die First * -Methoden häufiger verwendet werden als die Single * -Methoden.
quelle
Ich verstehe nicht, warum Sie verwenden,
FirstOrDefault(x=> x.ID == key)
wenn dies bei Verwendung viel schneller zu Ergebnissen führen könnteFind(key)
. Wenn Sie mit dem Primärschlüssel der Tabelle abfragen, gilt als Faustregel, immer zu verwendenFind(key)
.FirstOrDefault
sollte für Prädikate wie(x=> x.Username == username)
etc. verwendet werden.Dies hatte keine Abwertung verdient, da die Überschrift der Frage nicht spezifisch für linq on DB oder Linq to List / IEnumerable usw. war.
quelle
Find()
?