Rozważ metody rozszerzenia IEnumerable SingleOrDefault()
iFirstOrDefault()
Dokumenty MSDN, któreSingleOrDefault
:
Zwraca jedyny element sekwencji lub wartość domyślną, jeśli sekwencja jest pusta; ta metoda zgłasza wyjątek, jeśli w sekwencji jest więcej niż jeden element.
natomiast FirstOrDefault
z MSDN (przypuszczalnie przy używaniu OrderBy()
lub OrderByDescending()
albo wcale),
Zwraca pierwszy element sekwencji
Rozważ kilka przykładowych zapytań, nie zawsze jest jasne, kiedy użyć tych dwóch metod:
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?
Pytanie
Jakie konwencje stosujesz lub sugerujesz , decydując się na użycie SingleOrDefault()
i FirstOrDefault()
w zapytaniach LINQ?
źródło
Jeśli zestaw wyników zwraca 0 rekordów:
SingleOrDefault
zwraca wartość domyślną dla typu (np. wartość domyślna dla int wynosi 0)FirstOrDefault
zwraca wartość domyślną dla typuJeśli zestaw wyników zwróci 1 rekord:
SingleOrDefault
zwraca ten rekordFirstOrDefault
zwraca ten rekordJeśli zestaw wyników zwraca wiele rekordów:
SingleOrDefault
zgłasza wyjątekFirstOrDefault
zwraca pierwszy rekordWniosek:
Jeśli chcesz zgłosić wyjątek, jeśli zestaw wyników zawiera wiele rekordów, użyj
SingleOrDefault
.Jeśli zawsze chcesz 1 rekord, bez względu na to, co zawiera zestaw wyników, użyj
FirstOrDefault
źródło
FirstOrDefault
jest zwracany pierwszy rekord oznacza nowy rekord (ostatni) / stary rekord (pierwszy)? czy możesz mi wyjaśnić?Jest
pomiędzy dwoma.
Różnica semantyczna:
FirstOrDefault
zwraca pierwszą pozycję potencjalnie wielokrotną (lub domyślną, jeśli nie istnieje).SingleOrDefault
zakłada, że istnieje jeden element i zwraca go (lub domyślnie, jeśli nie istnieje). Wiele przedmiotów stanowi naruszenie umowy, zgłaszany jest wyjątek.Różnica wydajności
FirstOrDefault
jest zwykle szybszy, iteruje, dopóki nie znajdzie elementu, i musi iterować całą wyliczalność tylko wtedy, gdy go nie znajdzie. W wielu przypadkach istnieje duże prawdopodobieństwo znalezienia przedmiotu.SingleOrDefault
musi sprawdzić, czy jest tylko jeden element, a zatem zawsze iteruje całą wyliczalność. Mówiąc ściślej, iteruje, aż znajdzie drugi element i zgłasza wyjątek. Ale w większości przypadków nie ma drugiego elementu.Wniosek
Użyj,
FirstOrDefault
jeśli nie obchodzi Cię, ile jest przedmiotów lub gdy nie możesz sobie pozwolić na sprawdzenie wyjątkowości (np. W bardzo dużej kolekcji). Gdy zaznaczysz niepowtarzalność przy dodawaniu elementów do kolekcji, sprawdzenie ich ponownie może być zbyt drogie.Użyj,
SingleOrDefault
jeśli nie musisz zbytnio dbać o wydajność i chcesz upewnić się, że założenie pojedynczego elementu jest czytelne dla czytelnika i sprawdzone w czasie wykonywania.W praktyce używasz
First
/FirstOrDefault
często nawet w przypadkach, gdy zakładasz pojedynczy element, aby poprawić wydajność. Nadal powinieneś pamiętać, żeSingle
/SingleOrDefault
może poprawić czytelność (ponieważ określa założenie pojedynczego elementu) i stabilność (ponieważ sprawdza to) i odpowiednio go używać.źródło
SingleOrDefault
iteruje wiele obiektów podczas korzystania z Linq do Objects, ale czy nieSingleOrDefault
muszę iterować co najwyżej 2 elementów, jeśli Linq rozmawia na przykład z bazą danych? Zastanawiam się ..Enumerable
.Nikt nie wspomniał, że FirstOrDefault przetłumaczony na SQL ma rekord TOP 1, a SingleOrDefault ma TOP 2, ponieważ musi wiedzieć, że jest więcej niż 1 rekord.
źródło
FirstOrDefault()
dodaje,LIMIT 0,1
podczas gdySingleOrDefault()
nic nie dodaje.W przypadku LINQ -> SQL:
SingleOrDefault
FirstOrDefault
źródło
Używam
SingleOrDefault
w sytuacjach, w których moja logika dyktuje, że będzie to zero lub jeden wynik. Jeśli jest ich więcej, jest to sytuacja błędu, która jest pomocna.źródło
SingleOrDefault: Mówisz, że „Co najwyżej” jest jeden element pasujący do zapytania lub domyślny FirstOrDefault: Mówisz, że „Co najmniej” jeden element pasuje do zapytania lub domyślny
Powiedz to głośno następnym razem, gdy będziesz musiał dokonać wyboru, i prawdopodobnie wybierzesz mądrze. :)
źródło
FirstOrDefault. More correctly:
FirstOrDefault` = Dowolna liczba wyników, ale zależy mi tylko na pierwszym, może też nie być żadnych wyników.SingleOrDefault
= Istnieje 1 lub 0 wyników, jeśli jest ich więcej, oznacza to, że gdzieś jest błąd.First
= Jest co najmniej jeden wynik i chcę go.Single
= Jest dokładnie 1 wynik, nie więcej, nie mniej i chcę tego.W twoich przypadkach użyłbym następujących:
wybierz według ID == 5: tutaj możesz użyć SingleOrDefault, ponieważ oczekujesz jednej [lub żadnej] encji, jeśli masz więcej niż jedną encję o identyfikatorze 5, coś jest nie tak i na pewno wyjątek jest godny.
podczas wyszukiwania osób, których imię jest równe „Bobby”, może istnieć więcej niż jeden (całkiem możliwe, pomyślałbym), więc nie powinieneś używać ani Single, ani First, po prostu wybierz za pomocą operacji Where (jeśli „Bobby” zwraca zbyt wiele podmioty, użytkownik musi zawęzić wyszukiwanie lub wybrać jeden ze zwróconych wyników)
zamówienie według daty utworzenia powinno być również wykonane za pomocą operacji Where (mało prawdopodobne, aby istniała tylko jedna jednostka, sortowanie nie przydałoby się zbytnio;) oznacza to jednak, że chcesz posortować WSZYSTKIE jednostki - jeśli chcesz tylko JEDEN, użyj FirstOrDefault, Single wyrzuca za każdym razem, jeśli masz więcej niż jeden byt.
źródło
Oba są operatorami elementów i służą do wybierania pojedynczego elementu z sekwencji. Ale istnieje niewielka różnica między nimi. Operator SingleOrDefault () wyrzuciłby wyjątek, jeśli spełniony jest więcej niż jeden element, warunek, w którym jako FirstOrDefault () nie zgłosi żadnego wyjątku dla tego samego. Oto przykład.
źródło
W twoim ostatnim przykładzie:
Tak. Jeśli spróbujesz użyć,
SingleOrDefault()
a zapytanie spowoduje więcej niż rekord, otrzymasz i wyjątek. Jedynym momentem, kiedy możesz bezpiecznie korzystać,SingleOrDefault()
jest oczekiwanie tylko 1 i tylko 1 wyniku ...źródło
Tak jak teraz rozumiem
SingleOrDefault
będzie dobrze, jeśli będziesz wyszukiwać dane, które mają być unikalne, tj. Wymuszone przez ograniczenia DB, takie jak klucz podstawowy.Czy jest lepszy sposób na zapytanie o klucz podstawowy.
Zakładając, że mój TableAcc ma
i chcę zapytać o
AccountNumber 987654
, używamźródło
Moim zdaniem
FirstOrDefault
jest często nadużywany. W większości przypadków, gdy filtrujesz dane, możesz oczekiwać odzyskania kolekcji elementów pasujących do warunku logicznego lub pojedynczego unikalnego elementu poprzez jego unikalny identyfikator - taki jak użytkownik, książka, post itp. dlaczego możemy nawet powiedzieć, żeFirstOrDefault()
jest to zapach kodu, nie dlatego, że coś jest z nim nie tak, ale dlatego, że jest używany zbyt często. Ten post na blogu szczegółowo omawia ten temat. IMO przez większość czasuSingleOrDefault()
jest znacznie lepszą alternatywą, więc uważaj na ten błąd i upewnij się, że używasz najbardziej odpowiedniej metody, która jasno odzwierciedla twoją umowę i oczekiwania.źródło
Jednej rzeczy brakuje w odpowiedziach ....
Jeśli wyników jest wiele, FirstOrDefault bez zamówienia może przywrócić różne wyniki w oparciu o strategię indeksowania, z której kiedykolwiek korzystał serwer.
Osobiście nie mogę znieść widoku FirstOrDefault w kodzie, ponieważ według mnie programista nie dbał o wyniki. Z rozkazem może być przydatny jako sposób egzekwowania najnowszego / najwcześniejszego. Musiałem rozwiązać wiele problemów spowodowanych przez nieostrożnych programistów używających FirstOrDefault.
źródło
Zapytałem Google o użycie różnych metod w GitHub. Odbywa się to poprzez uruchomienie zapytania Google dla każdej metody i ograniczenie zapytania do domeny github.com i rozszerzenia pliku .cs przy użyciu zapytania „site: plik github.com: cs ...”
Wydaje się, że metody First * są częściej stosowane niż metody Single *.
źródło
Nie rozumiem, dlaczego używasz,
FirstOrDefault(x=> x.ID == key)
kiedy to można uzyskać wyniki znacznie szybciej, jeśli używaszFind(key)
. W przypadku zapytań przy użyciu klucza podstawowego tabeli należy zawsze stosować ogólną zasadęFind(key)
.FirstOrDefault
powinien być używany do takich predykatów jak(x=> x.Username == username)
itp.nie zasługiwało to na negatywną opinię, ponieważ nagłówek pytania nie był specyficzny dla linq na DB lub Linq na List / IEnumerable itp.
źródło
Find()
?