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

119

Mam straszny czas, szukając porównania różnych sposobów wyszukiwania pojedynczego elementu i kiedy używać każdego z nich.

Czy ktoś ma link, który porównuje wszystkie te elementy lub szybkie wyjaśnienie, dlaczego miałbyś używać jednego nad drugim? Czy jest jeszcze więcej operatorów, o których nie wiem?

Dziękuję Ci.

asfsadf
źródło

Odpowiedzi:

205

Oto przegląd różnych metod:

  • Find () - gdy chcesz uzyskać przedmiot za pomocą klucza podstawowego. Zwróci wartość null, jeśli nie może znaleźć elementu. Będzie wyglądać w kontekście przed przejściem do bazy danych (jak wskazał Yaron w komentarzach), co może być ważnym czynnikiem wydajności, jeśli chcesz uzyskać tę samą jednostkę wiele razy, podczas gdy ten sam kontekst jest żywy.

  • Single () - gdy spodziewasz się, że zapytanie zwróci dokładnie jeden element. Spowoduje to zgłoszenie wyjątku, jeśli zapytanie nie zwróci dokładnie jednego elementu.

  • SingleOrDefault () - gdy spodziewasz się, że zapytanie zwróci zero lub jeden element (czyli nie jesteś pewien, czy istnieje element o podanym kluczu). Spowoduje to zgłoszenie wyjątku, jeśli zapytanie nie zwróci zera lub jednego elementu.

  • First () - gdy oczekujesz, że zapytanie zwróci jeden lub więcej elementów, ale chcesz uzyskać dostęp tylko do pierwszego elementu w swoim kodzie (kolejność może być ważna w zapytaniu tutaj). Spowoduje to zgłoszenie wyjątku, jeśli zapytanie nie zwróci co najmniej jednego elementu.

  • FirstOrDefault () - gdy spodziewasz się, że zapytanie zwróci zero lub więcej elementów, ale chcesz uzyskać dostęp tylko do pierwszego elementu w swoim kodzie (tj. Nie jesteś pewien, czy istnieje element o podanym kluczu)

Steve Willcock
źródło
1
To zależy od scenariusza. Jeśli wiesz, że powinieneś zawsze odzyskać pojedynczy rekord z bazy danych, nie więcej, nie mniej, dla danego zapytania, to Single () jest „właściwym” do użycia. W innych sytuacjach inne mogą być bardziej odpowiednie. W poprzednich wersjach EF byliśmy ograniczeni do First () i FirstOrDefault (), które działają w scenariuszach, w których spodziewasz się pojedynczego rekordu, ale nie będą cię ostrzegać, jeśli faktycznie otrzymasz więcej niż ten pojedynczy rekord z powrotem, co może być ważne w zależności od sytuacja.
Steve Willcock
1
Dzięki. Nie wyobrażam sobie już, że potrzebuję First (), gdzie Single () nie byłoby lepsze. Gdybym był mniej gęsty, jestem pewien, że mógłbym docenić / zrozumieć, kiedy nadal używać First ().
asfsadf
1
Pierwsza () ma największy sens w przypadku, gdy chcesz pobrać tylko obiekt z najwyższą lub najniższą wartością, według której zamawiasz. Na przykład znajdź mi sprzedaż o najwyższej łącznej wartości. Sales.OrderByDescending(s => s.TotalValue).First();
Mike Chamberlain
5
Wszystkie komentarze wyglądają na ważną różnicę. Find () jest jedyną metodą, która przeszukuje kontekst przed trafieniem do bazy danych.
Yaron Levi
5
Inną kwestią jest, gdy zapytań do bazy danych SQL, Singlealbo SingleOrDefaultwyśle zapytanie do 2 rekordy (limit 2) podczas Firstlub FirstOrDefaultwyśle zapytanie do 1 (limit 1).
Bart Calixto
22

Zawsze używam FirstOrDefault. Jeśli naprawdę chcesz być wybredny w kwestii wydajności, powinieneś użyć FirstOrDefaultEF. Pod okładkami SingleOrDefaultużywa top (2) w zapytaniu, ponieważ musi sprawdzić, czy istnieje drugi wiersz, który pasuje do kryteriów, a jeśli tak, zgłasza wyjątek. Zasadniczo SingleOrDefaultmówisz, że chcesz zgłosić wyjątek, jeśli zapytanie zwróci więcej niż 1 rekord.

zeeshanhirani
źródło
5
Czy kiedykolwiek zmierzyłeś różnicę w wydajności między FirstOrDefaulti SingleOrDefaultaby była znacząca? Powiedziałbym, że w większości przypadków jest to przedwczesna optymalizacja.
Steven
Zwykle używam Single()lub SingleOrDefault()zwracam coś, z czego powinien istnieć tylko jeden . Robię to, aby wykrywać błędy, wykonując źle napisane zapytania, które zwracają więcej niż powinny, i kończą się niepowodzeniem. Przynajmniej moim zdaniem pomoże to zachować spójność danych w systemie. Oczywiście to jest wolniejsze, ale myślę, że nie jest dużo wolniejsze i jestem gotów zapłacić taką cenę.
mortb
15

To naprawdę bardzo proste: Singlezwraca pojedynczy element i zgłasza wyjątek, jeśli nie ma żadnego elementu lub więcej niż jeden element. Firstzwróci pierwszy przedmiot lub wyrzuci, gdy nie ma elementu. FirstOrDefaultzwróci pierwszą pozycję lub zwróci wartość domyślną (co ma miejsce nullw przypadku, gdy dany typ jest typem referencyjnym), gdy nie ma pozycji.

To jest zachowanie, które powinien mieć interfejs API. Należy jednak pamiętać, że podstawowa implementacja może mieć inne zachowanie. Chociaż Entity Framework jest zgodny z tym, O / RM, taki jak LLBLGen, może również zwrócić nullpodczas wywoływania, Firstco jest bardzo dziwne. To była bardzo dziwna (i uparta) decyzja projektanta IMO.

Steven
źródło
Dzięki, Steven. Myślę, że wciąż się zastanawiam, dlaczego używałbyś jednego nad drugim? Zawsze używałem FirstOrDefault () i byłem ciekawy, dlaczego wiele nowych przykładów, które widziałem, zostało przełączonych na Single (). Czy istnieje powód, aby przejść na Single ()? Czy są inne osoby, które również osiągają to samo, które powinienem rozważyć zamiast tego?
asfsadf
7
Jeśli podoba Ci się Twój kod do „nie szybko”, pierwszy () oraz pojedynczy () niech Twój kod bardziej precyzyjnie powiedzieć, czego oczekuje się (więc może nie inaczej)
Frank Schwieterman
3
Całkowicie zgadzam się z Frankiem. Chodzi również o komunikowanie intencji. Singlejasno wyraża, że ​​oczekujesz, że wynik będzie miał tylko jeden element.
Steven
8

Każda z czterech metod ma swoje miejsce; Chociaż tak naprawdę masz tylko dwie różne operacje.

  • Po pierwsze - oczekując zestawu wyników zawierającego wiele elementów, podaj mi pierwszy element z tego zestawu.
  • Pojedynczy - oczekując pojedynczego wyniku, daj mi ten przedmiot.

Wersja xxxxOrDefault () po prostu dodaje „Nie chcę uważać pustego zestawu wyników za wyjątkową okoliczność”.

Chris Shaffer
źródło
OK, więc wydaje mi się, że First () rzadko się przydaje. Trudno mi wymyślić scenariusz, w którym Single () nie byłaby pierwszą opcją. Masz przypadkową szybką jedną rękę? Dzięki.
asfsadf
3
Niestety wielu programistów używa First () lub FirstOrDefault () wyłącznie jako środek obronny, myśląc, że pozwoli to uniknąć wyjątku, gdy naprawdę ma potencjał do ukrycia prawdziwych problemów.
Matt H
3

Z drugiej strony możesz podzielić te metody według podstawowej logiki, na przykład:

  • Metoda wysyła zapytanie bezpośrednio do bazy danych : Single (), SingleOrDefault (), First (), FirstOrDefault ()
  • Metoda przeprowadzi wyszukiwanie w pamięci podręcznej jeszcze przed wysłaniem zapytania do bazy danych : Find ()

Szczegóły dotyczące wydajności, zwłaszcza w drugim przypadku, można znaleźć tutaj: https://msdn.microsoft.com/en-us/data/hh949853.aspx?f=255&MSPPError=-2147217396#3

Dodatkowo w pierwszej grupie można zdefiniować złożone zapytania, ale przy metodzie Find () można podać tylko klucz encji do wyszukiwania.

Kryszal
źródło
0

Single () i SingleOrDefault () są zwykle używane w przypadku unikalnych identyfikatorów, takich jak identyfikatory, podczas gdy First () lub FirstOrDefault () są zwykle używane w przypadku zapytania, które może mieć wiele wyników, ale potrzebujesz tylko „Top 1” .

Single () lub First () zgłosiłyby wyjątek, jeśli żaden wynik nie zostałby zwrócony, SingleOrDefault () i FirstOrDefault () przechwytują wyjątek i zwracają wartość null lub default (ResultDataType).

MilkTea027
źródło