Considere los métodos de extensión IEnumerable SingleOrDefault()
yFirstOrDefault()
MSDN documenta queSingleOrDefault
:
Devuelve el único elemento de una secuencia, o un valor predeterminado si la secuencia está vacía; Este método genera una excepción si hay más de un elemento en la secuencia.
mientras que FirstOrDefault
a partir de MSDN (presumiblemente cuando se utiliza un OrderBy()
o OrderByDescending()
o ninguno en absoluto),
Devuelve el primer elemento de una secuencia.
Considere un puñado de consultas de ejemplo, no siempre está claro cuándo usar estos dos métodos:
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?
Pregunta
¿Qué convenciones sigue o sugiere cuando decide usar SingleOrDefault()
y FirstOrDefault()
en sus consultas LINQ?
fuente
Si su conjunto de resultados devuelve 0 registros:
SingleOrDefault
devuelve el valor predeterminado para el tipo (por ejemplo, el valor predeterminado para int es 0)FirstOrDefault
devuelve el valor predeterminado para el tipoSi el conjunto de resultados devuelve 1 registro:
SingleOrDefault
devuelve ese registroFirstOrDefault
devuelve ese registroSi su conjunto de resultados devuelve muchos registros:
SingleOrDefault
lanza una excepciónFirstOrDefault
devuelve el primer registroConclusión:
Si desea que se produzca una excepción si el conjunto de resultados contiene muchos registros, use
SingleOrDefault
.Si siempre desea 1 registro sin importar el contenido del conjunto de resultados, use
FirstOrDefault
fuente
FirstOrDefault
se devuelve primer registro significa nuevo registro (último) / antiguo registro (primero) ¿me puede aclarar?Ahi esta
entre los dos.
Diferencia Semántica:
FirstOrDefault
devuelve un primer elemento potencialmente múltiple (o predeterminado si no existe ninguno).SingleOrDefault
asume que hay un solo elemento y lo devuelve (o predeterminado si no existe ninguno). Múltiples artículos son una violación del contrato, se lanza una excepción.Diferencia de rendimiento
FirstOrDefault
generalmente es más rápido, itera hasta que encuentra el elemento y solo tiene que iterar todo el enumerable cuando no lo encuentra. En muchos casos, hay una alta probabilidad de encontrar un artículo.SingleOrDefault
necesita verificar si solo hay un elemento y, por lo tanto, siempre itera todo el enumerable. Para ser precisos, itera hasta que encuentra un segundo elemento y arroja una excepción. Pero en la mayoría de los casos, no hay un segundo elemento.Conclusión
Úselo
FirstOrDefault
si no le importa cuántos elementos hay o cuándo no puede permitirse el lujo de comprobar la unicidad (por ejemplo, en una colección muy grande). Cuando verifica la unicidad al agregar los elementos a la colección, puede ser demasiado costoso volver a verificarlo al buscar esos elementos.Úselo
SingleOrDefault
si no tiene que preocuparse demasiado por el rendimiento y desea asegurarse de que la suposición de un solo elemento sea clara para el lector y se verifique en tiempo de ejecución.En la práctica, usas
First
/ aFirstOrDefault
menudo, incluso en los casos en que asumes un solo elemento, para mejorar el rendimiento. Aún debe recordar queSingle
/SingleOrDefault
puede mejorar la legibilidad (porque establece la suposición de un solo elemento) y la estabilidad (porque lo comprueba) y usarlo adecuadamente.fuente
SingleOrDefault
iterar sobre muchos objetos al usar Linq to Objects, pero noSingleOrDefault
tiene que iterar como máximo 2 elementos si Linq está hablando con una base de datos, por ejemplo. Me pregunto ...Enumerable
.Nadie ha mencionado que FirstOrDefault traducido en SQL registra TOP 1, y SingleOrDefault registra TOP 2, porque necesita saber si hay más de 1 registro.
fuente
FirstOrDefault()
agregaLIMIT 0,1
mientrasSingleOrDefault()
agrega nada.Para LINQ -> SQL:
SingleOrDefault
FirstOrDefault
fuente
Lo uso
SingleOrDefault
en situaciones donde mi lógica dicta que el resultado será cero o uno. Si hay más, es una situación de error, lo cual es útil.fuente
SingleOrDefault: Estás diciendo que "Como máximo" hay un elemento que coincide con la consulta o predeterminado FirstOrDefault: Estás diciendo que hay "Al menos" un elemento que coincide con la consulta o predeterminado
Dígalo en voz alta la próxima vez que necesite elegir y probablemente elija sabiamente. :)
fuente
FirstOrDefault. More correctly:
FirstOrDefault` = Cualquier número de resultados, pero solo me importa el primero, también puede que no haya resultados.SingleOrDefault
= Hay 1 o 0 resultados, si hay más, eso significa que hay un error en alguna parte.First
= Hay al menos un resultado, y lo quiero.Single
= Hay exactamente 1 resultado, ni más, ni menos, y quiero ese.En sus casos, usaría lo siguiente:
seleccione por ID == 5: está bien usar SingleOrDefault aquí, porque espera una entidad [o ninguna], si tiene más de una entidad con ID 5, hay algo mal y definitivamente una excepción digna.
al buscar personas cuyo nombre sea igual a "Bobby", puede haber más de uno (posiblemente creo), por lo que no debe usar Single ni First, solo seleccione con la operación Where (si "Bobby" devuelve demasiados entidades, el usuario tiene que refinar su búsqueda o elegir uno de los resultados devueltos)
el orden por fecha de creación también debe realizarse con una operación Where (es poco probable que solo tenga una entidad, la clasificación no sería de mucha utilidad); sin embargo, esto implica que desea ordenar TODAS las entidades; si solo desea UNA, use FirstOrDefault, Solo tiraría cada vez si tienes más de una entidad.
fuente
Ambos son operadores de elementos y se utilizan para seleccionar un solo elemento de una secuencia. Pero hay una pequeña diferencia entre ellos. El operador SingleOrDefault () lanzaría una excepción si se satisface más de un elemento, la condición donde FirstOrDefault () no arrojará ninguna excepción para el mismo. Aquí está el ejemplo.
fuente
En tu último ejemplo:
Si lo hace Si intenta usar
SingleOrDefault()
y la consulta da como resultado más que un registro, obtendrá una excepción. El único momento que puede usar de forma seguraSingleOrDefault()
es cuando espera solo 1 y solo 1 resultado ...fuente
Entonces, según tengo entendido ahora,
SingleOrDefault
será bueno si está buscando datos que garanticen que sean únicos, es decir, forzados por restricciones de DB como la clave primaria.¿O hay una mejor manera de consultar la clave primaria?
Suponiendo que mi TableAcc tiene
y quiero consultar un
AccountNumber 987654
, yo usofuente
En mi opinión
FirstOrDefault
se está usando demasiado. En la mayoría de los casos, cuando está filtrando datos, esperaría recuperar una colección de elementos que coinciden con la condición lógica o un único elemento único por su identificador único, como un usuario, libro, publicación, etc. por qué incluso podemos llegar a decir queFirstOrDefault()
es un olor a código no porque haya algo mal con él sino porque se está usando con demasiada frecuencia. Esta publicación de blog explora el tema en detalle. La OMI la mayoría de las vecesSingleOrDefault()
es una alternativa mucho mejor, así que tenga cuidado con este error y asegúrese de utilizar el método más apropiado que represente claramente su contrato y sus expectativas.fuente
Una cosa que se pierde en las respuestas ...
Si hay varios resultados, FirstOrDefault sin un pedido puede devolver resultados diferentes en función de la estrategia de índice utilizada por el servidor.
Personalmente, no puedo soportar ver FirstOrDefault en el código porque para mí dice que al desarrollador no le importaron los resultados. Con un pedido por, puede ser útil como una forma de hacer cumplir lo último / más temprano. He tenido que corregir muchos problemas causados por desarrolladores descuidados que usan FirstOrDefault.
fuente
Le pregunté a Google por el uso de los diferentes métodos en GitHub. Esto se realiza ejecutando una consulta de búsqueda de Google para cada método y limitando la consulta al dominio github.com y la extensión de archivo .cs mediante la consulta "sitio: archivo github.com: cs ..."
Parece que los métodos First * se usan más comúnmente que los métodos Single *.
fuente
No entiendo por qué estás usando
FirstOrDefault(x=> x.ID == key)
cuando esto podría recuperar resultados mucho más rápido si lo usasFind(key)
. Si está consultando con la clave principal de la tabla, la regla general es usar siempreFind(key)
.FirstOrDefault
debe usarse para cosas predicadas como(x=> x.Username == username)
etc.esto no merecía un voto negativo ya que el encabezado de la pregunta no era específico de linq en DB o Linq to List / IEnumerable, etc.
fuente
Find()
?