Tengo esta consulta:
int maxShoeSize = Workers
.Where(x => x.CompanyId == 8)
.Max(x => x.ShoeSize);
¿Qué habrá maxShoeSize
si la empresa 8 no tiene trabajadores?
ACTUALIZACIÓN:
¿Cómo puedo cambiar la consulta para obtener 0 y no una excepción?
maxShoeSize
?' si ya lo habías probadoRespuestas:
El cero en
DefaultIfEmpty
no es necesario.fuente
Max()
a una secuencia vacía da como resultado un error.Sé que esta es una pregunta antigua y la respuesta aceptada funciona, pero esta pregunta respondió a mi pregunta sobre si un conjunto tan vacío daría como resultado una excepción o un
default(int)
resultado.Sin embargo, la respuesta aceptada, aunque funciona, no es la solución ideal en mi humilde opinión, que no se da aquí. Por lo tanto, lo estoy proporcionando en mi propia respuesta para el beneficio de cualquiera que lo esté buscando.
El código original del OP fue:
Así es como lo escribiría para evitar excepciones y proporcionar un resultado predeterminado:
Esto hace que el tipo de retorno de la
Max
función seaint?
, lo que permite elnull
resultado y luego??
reemplaza elnull
resultado con0
.EDITAR
Solo para aclarar algo de los comentarios, Entity Framework actualmente no admite la
as
palabra clave, por lo que la forma de escribirla cuando se trabaja con EF sería:Dado que
[TypeOfWorkers]
podría ser un nombre de clase largo y es tedioso de escribir, he agregado un método de extensión para ayudar.Esto sólo mangos
int
, pero el mismo se podría hacer paralong
,double
o cualquier otro tipo de valor que necesita. El uso de este método de extensión es muy simple, simplemente pasa su función de selector y opcionalmente incluye un valor que se utilizará para nulo, que por defecto es 0. Por lo tanto, lo anterior podría reescribirse así:Esperemos que eso ayude a las personas aún más.
fuente
DefaultIfEmpty
respuesta más popular solo funciona bien cuandoMax
no se está haciendo una evaluación.Select
como intermediario cuando solo voy a usar una función agregada comoMax
en el resultado. También pienso (no lo he probado aún) que el SQL generado usaría una consulta de subselección adicional al hacer eso, mientras que el mío solo trataría con un conjunto vacío al devolver nulo. ¡Gracias por el voto y los comentarios! ;)ShoeSize
era en realidad en una relacionadaUniform
entidad, yo no usoWorkers.Where(x => x.CompanyId == 8).Select(x => x.Uniform).Max(x => x.ShoeSize)
, en vez me acaba de mantener toda la evaluación de laMax
función:Workers.Where(x => x.CompanyId == 8).Max(x => x.Uniform.ShoeSize)
. Prefiero utilizar la menor cantidad de métodos posible en mis consultas para permitir que EF tenga la mayor libertad para decidir cómo construir consultas de manera eficiente. ;-)public static TResult MaxOrDefault<TElement, TResult>(this IQueryable<TElement> items, Expression<Func<TElement, TResult>> selector, TResult defaultValue = default) where TResult : struct => items.Select(selector).Max(item => (TResult?)item) ?? defaultValue;
Max () no devolverá nada en ese caso.
Levantará InvalidOperationException ya que la fuente no contiene elementos.
fuente
InvalidOperationException
si los objetos en la lista son de tipo no anulable: docs.microsoft.com/en-us/dotnet/api/…fuente
Si esto es Linq to SQL, no me gusta usarlo
Any()
porque da como resultado múltiples consultas al servidor SQL.Si
ShoeSize
no es un campo anulable, entonces usar solo el.Max(..) ?? 0
no funcionará, pero lo siguiente sí:Absolutamente no cambia el SQL emitido, pero devuelve 0 si la secuencia está vacía porque cambia el
Max()
para devolver un enint?
lugar de unint
.fuente
(suponiendo que
ShoeSize
sea de tipoint
)Si
Workers
es unDbSet
oObjectSet
de Entity Framework, su consulta inicial arrojaría unInvalidOperationException
, pero no se quejaría de una secuencia vacía, pero se quejaría de que el valor materializado NULL no se puede convertir en unint
.fuente
Max lanzará System.InvalidOperationException "La secuencia no contiene elementos"
fuente
NB: la consulta con
DefaultIfEmpty()
puede ser significativamente más lenta . En mi caso, fue una consulta simple con.DefaultIfEmpty(DateTime.Now.Date)
.Era demasiado vago para perfilarlo, pero obviamente EF trató de obtener todas las filas y luego tomar el
Max()
valor.Conclusión: a veces el manejo
InvalidOperationException
puede ser la mejor opción.fuente
Puede usar un ternario dentro
.Max()
para manejar el predicado y establecer su valor;Debería manejar que la
Workers
colección sea nula / vacía si es una posibilidad, pero dependería de su implementación.fuente
Puedes probar esto:
fuente
Puede verificar si hay trabajadores antes de hacer el Max ().
fuente