LINQ:
Ist es effizienter, den Single()
Operator zu verwenden, First()
wenn ich sicher bin, dass die Abfrage einen einzelnen Datensatz zurückgibt?
Ist da ein Unterschied?
Ich weiß, dass andere geschrieben haben, warum Sie das eine oder das andere verwenden, aber ich dachte, ich würde veranschaulichen, warum Sie das eine NICHT verwenden sollten, wenn Sie das andere meinen .
Hinweis: In meinem Code, ich in der Regel verwenden FirstOrDefault()
und , SingleOrDefault()
aber das ist eine andere Frage.
Nehmen Sie zum Beispiel eine Tabelle, die Customers
mit einem zusammengesetzten Schlüssel ( ID
, Lang
) in verschiedenen Sprachen gespeichert wird :
DBContext db = new DBContext();
Customer customer = db.Customers.Where( c=> c.ID == 5 ).First();
Dieser obige Code führt einen möglichen Logikfehler ein (schwer zu verfolgen). Es wird mehr als ein Datensatz zurückgegeben (vorausgesetzt, Sie haben den Kundendatensatz in mehreren Sprachen), aber es wird immer nur der erste zurückgegeben ... was manchmal funktioniert ... aber nicht andere. Es ist unvorhersehbar.
Da Sie beabsichtigen, eine einmalige Customer
Verwendung zurückzugeben Single()
;
Folgendes würde eine Ausnahme auslösen (was in diesem Fall gewünscht wird):
DBContext db = new DBContext();
Customer customer = db.Customers.Where( c=> c.ID == 5 ).Single();
Dann schlägst du dich einfach auf die Stirn und sagst dir ... OOPS! Ich habe das Sprachfeld vergessen! Es folgt die richtige Version:
DBContext db = new DBContext();
Customer customer = db.Customers.Where( c=> c.ID == 5 && c.Lang == "en" ).Single();
First()
ist im folgenden Szenario nützlich:
DBContext db = new DBContext();
NewsItem newsitem = db.NewsItems.OrderByDescending( n => n.AddedDate ).First();
Es wird EIN Objekt zurückgegeben, und da Sie die Sortierung verwenden, ist es der letzte Datensatz, der zurückgegeben wird.
Mit Single()
wenn Sie es ausdrücklich immer 1 Datensatz zurückkehren wird dazu beitragen , logische Fehler fühlen Sie vermeiden sollten.
customers.Where(predicate).Single()
customers.Single(predicate)
?Single löst eine Ausnahme aus, wenn mehr als ein Datensatz gefunden wird, der den Kriterien entspricht. Zuerst wird immer der erste Datensatz aus der Liste ausgewählt. Wenn die Abfrage nur 1 Datensatz zurückgibt, können Sie fortfahren
First()
.Beide lösen eine
InvalidOperationException
Ausnahme aus, wenn die Sammlung leer ist. Alternativ können Sie verwendenSingleOrDefault()
. Dies löst keine Ausnahme aus, wenn die Liste leer istquelle
Single()
SingleOrDefault ()
Zuerst()
FirstOrDefault ()
quelle
First
wenn 1 oder mehr Elemente erwartet werden , nicht nur "mehr als 1" undFirstOrDefault
mit einer beliebigen Anzahl von Elementen.Es gibt einen subtilen semantischen Unterschied zwischen diesen beiden Methoden.
Verwenden Sie
Single
diese Option , um das erste (und einzige) Element aus einer Sequenz abzurufen, die ein Element und nicht mehr enthalten soll. Wenn die Sequenz mehr als ein Element enthält, wird durch Ihren Aufruf vonSingle
eine Ausnahme ausgelöst, da Sie angegeben haben, dass nur ein Element vorhanden sein soll.Verwenden Sie
First
diese Option , um das erste Element aus einer Sequenz abzurufen, die eine beliebige Anzahl von Elementen enthalten kann. Wenn die Sequenz mehr als ein Element enthält, wird Ihr Aufruf vonFirst
keine Ausnahme ausgelöst, da Sie angegeben haben, dass Sie nur das erste Element in der Sequenz benötigen und es egal ist, ob weitere vorhanden sind.Wenn die Sequenz keine Elemente enthält, werden bei beiden Methodenaufrufen Ausnahmen ausgelöst, da beide Methoden erwarten, dass mindestens ein Element vorhanden ist.
quelle
Wenn Sie nicht ausdrücklich möchten, dass eine Ausnahme für den Fall ausgelöst wird, dass mehr als ein Element vorhanden ist, verwenden Sie
First()
.Beide sind effizient, nehmen Sie den ersten Punkt.
First()
ist etwas effizienter, da es nicht die Mühe macht, zu überprüfen, ob es ein zweites Element gibt.Der einzige Unterschied besteht darin,
Single()
dass zunächst nur ein Element in der Aufzählung erwartet wird und eine Ausnahme ausgelöst wird, wenn mehr als ein Element vorhanden ist. Sie verwenden.Single()
diese Option , wenn in diesem Fall speziell eine Ausnahme ausgelöst werden soll.quelle
Wenn ich mich erinnere, prüft Single (), ob nach dem ersten ein anderes Element vorhanden ist (und löst eine Ausnahme aus, wenn dies der Fall ist), während First () nach dem Abrufen stoppt. Beide lösen eine Ausnahme aus, wenn die Sequenz leer ist.
Persönlich benutze ich immer First ().
quelle
In Bezug auf die Leistung: Ein Mitarbeiter und ich diskutierten die Leistung von Single vs First (oder SingleOrDefault vs FirstOrDefault) und ich argumentierte für den Punkt, dass First (oder FirstOrDefault) schneller sein und die Leistung verbessern würde (ich möchte unsere App entwickeln) schneller laufen).
Ich habe mehrere Beiträge zu Stack Overflow gelesen, in denen dies diskutiert wird. Einige sagen, dass es kleine Leistungssteigerungen gibt, wenn First anstelle von Single verwendet wird. Dies liegt daran, dass First einfach das erste Element zurückgibt, während Single alle Ergebnisse scannen muss, um sicherzustellen, dass kein Duplikat vorhanden ist (dh, wenn das Element in der ersten Zeile der Tabelle gefunden wird, wird weiterhin jede zweite Zeile gescannt Stellen Sie sicher, dass es keinen zweiten Wert gibt, der der Bedingung entspricht, die dann einen Fehler auslösen würde. Ich hatte das Gefühl, auf einem soliden Boden zu stehen, da „First“ schneller als „Single“ war, und machte mich daran, dies zu beweisen und die Debatte zu beenden.
Ich habe einen Test in meiner Datenbank eingerichtet und 1.000.000 Zeilen ID UniqueIdentifier Foreign UniqueIdentifier Info nvarchar (50) hinzugefügt (gefüllt mit Zeichenfolgen von „0“ bis „999.9999“.
Ich habe die Daten geladen und die ID als Primärschlüsselfeld festgelegt.
Mit LinqPad wollte ich zeigen, dass es viel schlimmer wäre, wenn Sie mit Single nach einem Wert für 'Foreign' oder 'Info' suchen, als mit First.
Ich kann die Ergebnisse nicht erklären. In fast allen Fällen war die Verwendung von Single oder SingleOrDefault etwas schneller. Das ergibt für mich keinen logischen Sinn, aber ich wollte das teilen.
Beispiel: Ich habe die folgenden Abfragen verwendet:
Ich habe ähnliche Abfragen im Schlüsselfeld "Fremd" versucht, bei denen es sich nicht um indizierte Überlegungen handelte, die beweisen würden, dass First schneller ist, Single jedoch in meinen Tests immer etwas schneller.
quelle
Sie sind anders. Beide behaupten, dass die Ergebnismenge nicht leer ist, aber single behauptet auch, dass es nicht mehr als 1 Ergebnis gibt. Ich persönlich verwende Single in Fällen, in denen ich nur ein Ergebnis erwarte, nur weil es ein Fehler ist, mehr als ein Ergebnis zurückzubekommen, und wahrscheinlich als solches behandelt werden sollte.
quelle
Sie können ein einfaches Beispiel ausprobieren, um einen Unterschied zu erzielen. Ausnahme wird in Zeile 3 ausgelöst;
quelle
Viele Leute, die ich kenne, verwenden FirstOrDefault (), aber ich verwende SingleOrDefault () häufiger, da es häufig zu einer Art Dateninkonsistenz kommen würde, wenn es mehr als eine gäbe. Dies betrifft jedoch LINQ-to-Objects.
quelle
Die Datensätze in der Entität Mitarbeiter:
Employeeid = 1
: Nur ein Mitarbeiter mit dieser IDFirstname = Robert
: Mehr als ein Mitarbeiter mit diesem NamenEmployeeid = 10
: Kein Mitarbeiter mit dieser IDJetzt ist es notwendig zu verstehen, was
Single()
und wasFirst()
im Detail bedeutet.Single()
Single () wird verwendet, um einen einzelnen Datensatz zurückzugeben, der eindeutig in einer Tabelle vorhanden ist. Die folgende Abfrage gibt also den Mitarbeiter zurück, dessen,
employeed =1
weil wir nur einen Mitarbeiter haben, dessen 1Employeed
ist. Wenn wir zwei Datensätze fürEmployeeId = 1
haben, wird ein Fehler ausgegeben (siehe die Fehler unten in der zweiten Abfrage, für die wir ein Beispiel verwendenFirstname
.Das obige gibt einen einzelnen Datensatz zurück, der 1 hat
employeeId
Das Obige löst eine Ausnahme aus, da mehrere Datensätze in der Tabelle für enthalten sind
FirstName='Robert'
. Die Ausnahme wird seinDies löst erneut eine Ausnahme aus, da für id = 10 kein Datensatz vorhanden ist. Die Ausnahme wird sein
Denn
EmployeeId = 10
es wird null zurückgeben, aber während wir es benutzenSingle()
, wird es einen Fehler auslösen. Um Nullfehler zu behandeln, sollten wir verwendenSingleOrDefault()
.Zuerst()
First () gibt aus mehreren Datensätzen die entsprechenden Datensätze zurück, die in aufsteigender Reihenfolge sortiert sind,
birthdate
sodass 'Robert' zurückgegeben wird, der am ältesten ist.Oben sollte der älteste zurückgegeben werden, Robert gemäß DOB.
Oben wird eine Ausnahme ausgelöst, da kein Datensatz für id = 10 vorhanden ist. Um eine Null - Ausnahme zu vermeiden wir verwenden sollten ,
FirstOrDefault()
als vielmehrFirst()
.Hinweis: Wir können nur
First()
/ verwenden,Single()
wenn wir absolut sicher sind, dass kein Nullwert zurückgegeben werden kann.Verwenden Sie in beiden Funktionen SingleOrDefault () ODER FirstOrDefault (), das eine Null-Ausnahme behandelt. Wenn kein Datensatz gefunden wird, wird Null zurückgegeben.
quelle