90

Mam diabła czasu, znajdując porównanie różnych sposobów kwerendy dla pojedynczego elementu i kiedy używać każdego.Entity Framework 4 Single() vs First() vs FirstOrDefault()

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

Dziękuję.

Odpowiedz

157

Oto przegląd różnych metod:

  • Find() - gdy chcesz uzyskać element, klucz podstawowy. Zwróci wartość null, jeśli nie może znaleźć elementu. Zanim przejdziemy do bazy danych, będzie to wyglądać w kontekście (jak zauważył Yaron w komentarzach), co może być ważnym czynnikiem wydajności, jeśli chcemy otrzymać ten sam podmiot wiele razy, podczas gdy ten sam kontekst jest żywy.

  • Single() - gdy oczekujesz, że jeden przedmiot zostanie zwrócony przez zapytanie. Spowoduje to zgłoszenie wyjątku, jeśli zapytanie nie zwróci dokładnie jednego elementu.

  • SingleOrDefault() - gdy oczekujesz, że zero lub jeden element zostanie zwrócony przez zapytanie (tzn. Nie masz pewności, czy istnieje element z danym kluczem). Spowoduje to zgłoszenie wyjątku, jeśli zapytanie nie zwróci wartości zero lub jednego elementu.

  • Po pierwsze() - kiedy oczekuje się, że jeden lub więcej produktów zostanie zwrócony przez zapytanie, ale użytkownik chce uzyskać dostęp tylko do pierwszego elementu w kodzie (w tym miejscu może być ważne zamówienie). Spowoduje to zgłoszenie wyjątku, jeśli zapytanie nie zwróci co najmniej jednego elementu.

  • FirstOrDefault() - gdy oczekujesz, że zero lub więcej elementów zostanie zwróconych przez zapytanie, ale chcesz uzyskać dostęp tylko do pierwszego elementu w kodzie (np. Nie masz pewności, czy element z danym kluczem istnieje)

+2

Ah, dzięki. Jeszcze inny, który pozornie osiąga to samo - lol. – asfsadf

+0

Czy używasz wszystkich 4 w zależności od scenariusza lub trzymasz się tylko jednego? – asfsadf

+1

To zależy od scenariusza. Jeśli wiesz, że zawsze powinieneś otrzymać pojedynczy rekord z bazy danych, nie więcej, nie mniej, dla danego zapytania, wtedy Single() jest "właściwym" do użycia. W innych sytuacjach inne mogą być bardziej odpowiednie. W poprzednich wersjach EF ograniczaliśmy się do First() i FirstOrDefault(), które działają w scenariuszach, w których oczekuje się pojedynczego rekordu, ale nie będą ostrzegać, jeśli rzeczywiście otrzymasz więcej niż jeden rekord, co może być ważne w zależności od sytuacja. –

15

To naprawdę bardzo proste: Single zwraca jeden element i generuje wyjątek, jeśli nie ma żadnego lub więcej niż jednego elementu. First zwróci pierwszy element lub wyrzuci, gdy nie ma elementu. FirstOrDefault zwróci pierwszą pozycję lub zwróci domyślną wartość (która jest null, jeśli dany typ jest typem odniesienia), gdy nie ma elementu.

To zachowanie API powinno mieć. Należy jednak zauważyć, że podstawowa implementacja może mieć inne zachowanie. Podczas gdy Entity Framework jest temu posłuszny, O/RM jak LLBLGen może również zwrócić null podczas wywoływania First co jest bardzo dziwną rzeczą. To była bardzo dziwna (i uparta) decyzja projektanta IMO.

+0

Dzięki Steven. Chyba 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, zmieniło się na Single(). Czy istnieje powód, aby przejść na Single()? Czy są inni, którzy również robią to samo, co powinienem rozważyć zamiast tego? – asfsadf

+7

Jeśli podoba ci się kod "szybko się zawieść", First() i Single() niech twój kod precyzyjniej powie, czego się spodziewasz (aby inaczej było inaczej) –

+3

Całkowicie zgadzam się z Frankiem. Chodzi także o komunikację intencji. 'Single' wyraża wyraźnie, że oczekujesz, że wynik będzie zawierał tylko jeden element. – Steven

8

Cztery metody mają swoje miejsce; Chociaż naprawdę masz tylko dwie różne operacje.

  • Po pierwsze - Oczekując zestawu wyników, który zawiera wiele elementów, daj mi pierwszy przedmiot w tym zestawie.
  • Single - Oczekując jednego wyniku z powrotem, daj mi ten przedmiot.

Wersja xxxxOrDefault() po prostu dodaje: "Nie chcę, aby pusty zestaw wyników był wyjątkową okolicznością."

+0

OK, więc wydaje mi się, że First() rzadko by się przydało. Trudno mi wymyślić scenariusz, w którym Single() nie byłby pierwszą opcją. Masz przypadek? Dzięki. – asfsadf

+3

Niestety, wielu deweloperów używa First() lub FirstOrDefault() jako środka defensywnego, myśląc, że uniknie wyjątku, gdy naprawdę będzie w stanie ukryć prawdziwe problemy. –

16

Zawsze staram się używać FirstOrDefault.Jeśli naprawdę chcesz być wybredny z wydajnością, powinieneś użyć FirstOrDefault w EF. Pod okładkami SingleOrDefault używa top (2) w zapytaniu, ponieważ musi sprawdzić, czy istnieje drugi rząd, spełniających kryteria, a jeśli tak, to zgłasza wyjątek. Zasadniczo w SingleOrDefault mówisz że u dbają, aby rzucić wyjątek, jeśli zapytanie zwraca więcej niż 1 rekord.

+4

Czy kiedykolwiek mierzysz różnicę wydajności między 'FirstOrDefault' a' SingleOrDefault', aby być znaczącym? Powiedziałbym, że w większości przypadków jest to przedwczesna optymalizacja. – Steven

+1

[Ten facet zrobił] (http://stackoverflow.com/a/8265919/634824) –

0

pojedynczy() i SingleOrDefault() jest zwykle używany na unikalnych identyfikatorach, takich jak ID, a First() lub FirstOrDefault() jest zwykle używany do zapytania, które może mieć wiele wyników, ale chcesz tylko "Top 1".

pojedynczy() lub Pierwsze() będzie wyjątek, jeśli nie zostanie zwrócony wynik, SingleOrDefault() i FirstOrDefault() połowy wyjątek i zwraca wartość null lub default (ResultDataType).

1

Z drugiej strony, można podzielić te metody logika rdzenia, tak:

  • metoda będzie zapytanie do bazy danych bezpośrednio: pojedynczy(), SingleOrDefault(), najpierw(), FirstOrDefault()
  • Metoda wykona wyszukiwanie w pamięci podręcznej jeszcze przed wydaniem kwerendy w bazie danych: find()

Dla niektórych szczegółów wydajności, szczególnie w drugim przypadku można sprawdzić tutaj: https://msdn.microsoft.com/en-us/data/hh949853.aspx?f=255&MSPPError=-2147217396#3

Ponadto, w pierwszej grupie można zdefiniować złożone zapytania, ale z find() sposób można zapewnić jedynie podmiot klucz do wyszukiwania.

Powiązane problemy