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


119

Mi sto divertendo un mondo a trovare un confronto tra i diversi modi di eseguire query per un singolo elemento e quando utilizzarli.

Qualcuno ha un collegamento che confronta tutti questi o una rapida spiegazione del motivo per cui useresti uno sull'altro? Ci sono ancora altri operatori di cui non sono a conoscenza?

Grazie.

Risposte:


205

Ecco una panoramica dei diversi metodi:

  • Find () - quando si desidera ottenere un elemento dalla chiave primaria. Questo restituirà null se non riesce a trovare un elemento. Guarderà nel contesto prima di andare al database (come sottolineato da Yaron nei commenti) che può essere un importante fattore di efficienza se è necessario ottenere la stessa entità più volte mentre lo stesso contesto è vivo.

  • Single (): quando ti aspetti che una query restituisca esattamente un elemento. Ciò genererà un'eccezione se la query non restituisce esattamente un elemento.

  • SingleOrDefault () - quando ti aspetti che zero o un elemento venga restituito da una query (ovvero non sei sicuro che esista un elemento con una determinata chiave). Ciò genererà un'eccezione se la query non restituisce zero o un elemento.

  • Primo () - quando ti aspetti che uno o più elementi vengano restituiti da una query ma desideri accedere solo al primo elemento nel tuo codice (l'ordinamento potrebbe essere importante nella query qui). Ciò genererà un'eccezione se la query non restituisce almeno un elemento.

  • FirstOrDefault () - quando ti aspetti che zero o più elementi vengano restituiti da una query ma desideri accedere solo al primo elemento nel tuo codice (ovvero non sei sicuro che esista un elemento con una determinata chiave)


1
Dipende dallo scenario. Se sai che dovresti sempre recuperare un singolo record dal db, né più né meno, per una data query, Single () è quello "giusto" da usare. In altre situazioni le altre possono essere più appropriate. Nelle versioni precedenti di EF eravamo limitati a First () e FirstOrDefault () che funzionano per scenari in cui ti aspetti un singolo record ma non ti avviseranno se in realtà ottieni più di quel singolo record indietro che potrebbe essere importante a seconda di la situazione.
Steve Willcock

1
Grazie. Non riesco più a vedere me stesso bisogno di First (), dove Single () non sarebbe migliore. Se fossi meno ottuso, sono sicuro che potrei apprezzare / capire quando usare ancora First ().
asfsadf

1
First () ha più senso nel caso in cui si desideri recuperare solo l'oggetto con il valore più alto o più basso di quello che si sta ordinando. Ad esempio, trovami la vendita con il valore totale più alto. Sales.OrderByDescending(s => s.TotalValue).First();
Mike Chamberlain

5
Tutti i commenti sembrano una differenza importante. Find () è l'unico metodo che ricerca il contesto prima di premere il db.
Yaron Levi

5
Un altro punto è quando si esegue una query su un database sql Singleo SingleOrDefaultsi interrogherà per 2 record (limite 2) mentre Firsto FirstOrDefaultsi interrogherà per 1 (limite 1).
Bart Calixto

22

Tendo sempre a usare FirstOrDefault. Se vuoi davvero essere pignolo con le prestazioni, dovresti usarlo FirstOrDefaultin EF. Under the covers SingleOrDefaultutilizza top (2) nella query perché deve controllare se è presente una seconda riga che corrisponde ai criteri e, in caso affermativo, genera un'eccezione. Fondamentalmente SingleOrDefaultstai dicendo che vuoi lanciare un'eccezione se la tua query restituisce più di 1 record.


5
Hai mai misurato la differenza di prestazioni tra FirstOrDefaulte SingleOrDefaultper essere significativa? Direi che è un'ottimizzazione prematura nella maggior parte dei casi.
Steven

Tendo a usare Single()o SingleOrDefault()quando restituisco qualcosa di cui dovrebbe esistere solo uno . Il motivo per cui lo faccio è individuare i bug eseguendo query scritte male, che restituiscono più di quanto dovrebbero, falliscono. Almeno nella mia mente, questo aiuterà a mantenere coerenti i dati nel sistema. Ovviamente questo è più lento, ma immagino che non sia molto più lento e sono disposto a pagare quel prezzo.
mortb

15

È davvero molto semplice: Singlerestituisce un singolo elemento e genera un'eccezione se non ce n'è nessuno o più di un elemento. Firstrestituirà il primo oggetto o lancerà quando non è presente alcun oggetto. FirstOrDefaultrestituirà il primo elemento o restituirà il valore predefinito (che è nullnel caso in cui il tipo specificato sia un tipo di riferimento) quando non è presente alcun elemento.

Questo è il comportamento che dovrebbe avere l'API. Si noti tuttavia che l'implementazione sottostante potrebbe avere un comportamento diverso. Mentre Entity Framework obbedisce a questo, un O / RM come LLBLGen può anche tornare nullquando si chiama, il Firstche è una cosa molto strana. Questa è stata una decisione molto strana (e testarda) del designer IMO.


Grazie Steven. Immagino che mi stia ancora chiedendo perché useresti uno sull'altro? Ho sempre usato FirstOrDefault () ed ero curioso di sapere perché molti dei nuovi esempi che ho visto sono passati a Single (). C'è un motivo per passare a Single ()? Ce ne sono altri che realizzano la stessa cosa, che dovrei invece considerare?
asfsadf

7
Se ti piace che il tuo codice "fallisca velocemente", First () e Single () lascia che il tuo codice dica più precisamente cosa ci si aspetta (quindi potrebbe fallire altrimenti)
Frank Schwieterman

3
Sono totalmente d'accordo con Frank. Si tratta anche di comunicare l'intento. Singleesprime chiaramente che ti aspetti che il risultato abbia un solo elemento.
Steven

8

I quattro metodi hanno ciascuno il loro posto; Anche se in realtà hai solo due operazioni diverse.

  • Primo: aspettandomi un set di risultati che contiene più elementi, dammi il primo elemento in quel set.
  • Singolo - Mi aspetto un singolo risultato indietro, dammi quell'elemento.

La versione xxxxOrDefault () aggiunge semplicemente "Non voglio considerare un set di risultati vuoto come una circostanza eccezionale."


OK, quindi mi sembra che First () raramente tornerebbe utile. Sto avendo difficoltà a trovare uno scenario in cui Single () non sarebbe la prima opzione. Hai una mano veloce, per caso? Grazie.
asfsadf

3
Sfortunatamente molti sviluppatori usano First () o FirstOrDefault () puramente come misura difensiva, pensando che eviterà un'eccezione quando ha davvero il potenziale per nascondere problemi reali.
Matt H

3

Dall'altro lato, puoi dividere questi metodi per la logica di base, in questo modo:

  • Il metodo interrogherà direttamente il database : Single (), SingleOrDefault (), First (), FirstOrDefault ()
  • Il metodo eseguirà una ricerca nella cache prima ancora di inviare la query sul database : Find ()

Per alcuni dettagli sulle prestazioni, specialmente nel secondo caso, puoi guardare qui: https://msdn.microsoft.com/en-us/data/hh949853.aspx?f=255&MSPPError=-2147217396#3

Inoltre, nel primo gruppo puoi definire query complesse, ma con il metodo Find () puoi fornire solo la chiave di entità per la ricerca.


0

Single () e SingleOrDefault () vengono solitamente utilizzati su identificatori univoci come ID, mentre First () o FirstOrDefault () vengono solitamente utilizzati per una query che potrebbe avere più risultati ma si desidera solo il "Top 1" .

Single () o First () genererebbero un'eccezione se non viene restituito alcun risultato, SingleOrDefault () e FirstOrDefault () rilevano l'eccezione e restituiscono null o default (ResultDataType).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.