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

119

Me está costando mucho encontrar una comparación de las diferentes formas de consultar un solo elemento y cuándo usar cada una.

¿Alguien tiene un enlace que compare todos estos, o una explicación rápida de por qué usaría uno sobre el otro? ¿Hay todavía más operadores que desconozco?

Gracias.

asfsadf
fuente

Respuestas:

205

Aquí hay una descripción general de los diferentes métodos:

  • Find (): cuando desee obtener un elemento por clave principal. Esto devolverá nulo si no puede encontrar un artículo. Verá en el contexto antes de ir a la base de datos (como lo señaló Yaron en los comentarios), lo que puede ser un factor de eficiencia importante si necesita obtener la misma entidad varias veces mientras el mismo contexto está vivo.

  • Single (): cuando espera que una consulta devuelva exactamente un elemento. Esto generará una excepción si la consulta no devuelve exactamente un elemento.

  • SingleOrDefault (): cuando espera que una consulta devuelva cero o un elemento (es decir, no está seguro de si existe un elemento con una clave determinada). Esto generará una excepción si la consulta no devuelve cero o un elemento.

  • Primero (): cuando espera que una consulta devuelva uno o más elementos, pero solo desea acceder al primer elemento de su código (el pedido podría ser importante en la consulta aquí). Esto generará una excepción si la consulta no devuelve al menos un elemento.

  • FirstOrDefault (): cuando espera que una consulta devuelva cero o más elementos, pero solo desea acceder al primer elemento de su código (es decir, no está seguro de si existe un elemento con una clave determinada)

Steve Willcock
fuente
1
Depende del escenario. Si sabe que siempre debe obtener un solo registro de la base de datos, ni más ni menos, para una consulta determinada, entonces Single () es el "correcto" para usar. En otras situaciones, las otras pueden ser más apropiadas. En versiones anteriores de EF, estábamos limitados a First () y FirstOrDefault () que funcionan para escenarios en los que espera un solo registro, pero no le advertirán si en realidad obtiene más de ese único registro que podría ser importante dependiendo de la situación.
Steve Willcock
1
Gracias. Ya no me veo necesitando First (), donde Single () no sería mejor. Si fuera menos denso, estoy seguro de que aún podría apreciar / entender cuándo usar First ().
asfsadf
1
Primero () tiene más sentido en el caso de que desee recuperar solo el objeto con el valor más alto o más bajo de lo que está ordenando. Por ejemplo, busque la venta con el valor total más alto. Sales.OrderByDescending(s => s.TotalValue).First();
Mike Chamberlain
5
Todos los comentarios pasan por alto una diferencia importante. Find () es el único método que busca en el contexto antes de acceder a la base de datos.
Yaron Levi
5
Otro punto es al consultar una base de datos SQL, Singleo SingleOrDefaultconsultará 2 registros (límite 2) mientras que Firsto FirstOrDefaultconsultará 1 (límite 1).
Bart Calixto
22

Yo siempre suelo usar FirstOrDefault. Si realmente quieres ser exigente con el rendimiento, debes usar FirstOrDefaultEF. Debajo de las cubiertas SingleOrDefaultusa top (2) en la consulta porque necesita verificar si hay una segunda fila que coincide con los criterios y, si lo hace, lanza una excepción. Básicamente SingleOrDefault, está diciendo que desea lanzar una excepción si su consulta devuelve más de 1 registro.

zeeshanhirani
fuente
5
¿Alguna vez ha medido que la diferencia de rendimiento entre FirstOrDefaulty SingleOrDefaultsea ​​significativa? Yo diría que es una optimización prematura en la mayoría de los casos.
Steven
Tiendo a usar Single()o SingleOrDefault()cuando devuelvo algo de lo cual solo debería existir uno . La razón por la que lo hago es para detectar errores al realizar consultas mal escritas, que devuelven más de lo que deberían, fallan. Al menos en mi opinión, esto ayudará a mantener la coherencia de los datos en el sistema. Por supuesto, esto es más lento, pero supongo que no es mucho más lento y estoy dispuesto a pagar ese precio.
mortb
15

Es realmente muy simple: Singledevuelve un solo elemento y lanza una excepción si no hay ninguno o más de un elemento. Firstdevolverá el primer artículo o lo arrojará cuando no haya ningún artículo. FirstOrDefaultdevolverá el primer artículo o devolverá el valor predeterminado (que es nullen caso de que el tipo dado sea un tipo de referencia) cuando no haya ningún artículo.

Este es el comportamiento que se supone que debe tener la API. Sin embargo, tenga en cuenta que la implementación subyacente podría tener un comportamiento diferente. Si bien Entity Framework obedece a esto, un O / RM como LLBLGen también puede regresar nullal llamar, lo Firstcual es algo muy extraño. Esta fue una decisión muy extraña (y obstinada) del diseñador IMO.

Steven
fuente
Gracias Steven. Supongo que todavía me pregunto por qué usarías uno sobre el otro. Siempre he usado FirstOrDefault () y tenía curiosidad por saber por qué muchos de los ejemplos nuevos que he visto se han cambiado a Single (). ¿Hay alguna razón para cambiar a Single ()? ¿Hay otros que también logran lo mismo, que debería considerar en su lugar?
asfsadf
7
Si desea que su código "falle rápidamente", First () y Single () permiten que su código diga con mayor precisión lo que se espera (para que, de lo contrario, pueda fallar)
Frank Schwieterman
3
Estoy totalmente de acuerdo con Frank. También se trata de comunicar la intención. Singleexpresa claramente que solo espera que el resultado tenga un elemento.
Steven
8

Cada uno de los cuatro métodos tiene su lugar; Aunque en realidad solo tienes dos operaciones diferentes.

  • Primero: esperando un conjunto de resultados que contenga varios elementos, dame el primer elemento de ese conjunto.
  • Soltero - Esperando un único resultado de vuelta, dame ese artículo.

La versión xxxxOrDefault () simplemente agrega "No quiero considerar un conjunto de resultados vacío como una circunstancia excepcional".

Chris Shaffer
fuente
De acuerdo, me parece que First () rara vez sería útil. Estoy teniendo dificultades para pensar en un escenario en el que Single () no sería la primera opción. ¿Tienes uno rápido, por casualidad? Gracias.
asfsadf
3
Desafortunadamente, muchos desarrolladores usan First () o FirstOrDefault () simplemente como una medida defensiva, pensando que evitará una excepción cuando en realidad solo tiene el potencial de ocultar problemas reales.
Matt H
3

Por otro lado, puede dividir estos métodos por la lógica central, así:

  • El método consultará la base de datos directamente : Single (), SingleOrDefault (), First (), FirstOrDefault ()
  • El método realizará una búsqueda en la caché incluso antes de emitir la consulta en la base de datos : Find ()

Para obtener algunos detalles de rendimiento, especialmente en el segundo caso, puede consultar aquí: https://msdn.microsoft.com/en-us/data/hh949853.aspx?f=255&MSPPError=-2147217396#3

Además, en el primer grupo puede definir consultas complejas, pero con el método Find () puede proporcionar solo la clave de entidad para la búsqueda.

Kryszal
fuente
0

Single () y SingleOrDefault () generalmente se usan en identificadores únicos como ID, mientras que First () o FirstOrDefault () generalmente se usan para una consulta que podría tener varios resultados pero que solo desea el "Top 1" .

Single () o First () arrojarían una excepción si no se devuelve ningún resultado, SingleOrDefault () y FirstOrDefault () detectan la excepción y devuelven un valor nulo o predeterminado (ResultDataType).

MilkTea027
fuente