Eu tenho esta consulta:
int maxShoeSize = Workers
.Where(x => x.CompanyId == 8)
.Max(x => x.ShoeSize);
O que acontecerá maxShoeSize
se a empresa 8 não tiver trabalhadores?
ATUALIZAÇÃO:
Como posso alterar a consulta para obter 0 e não uma exceção?
maxShoeSize
?" se você já experimentou.Respostas:
O zero in
DefaultIfEmpty
não é necessário.fonte
Max()
uma sequência vazia resulta em um erro.Eu sei que essa é uma pergunta antiga e a resposta aceita funciona, mas essa pergunta respondeu à minha pergunta sobre se um conjunto vazio resultaria em uma exceção ou em um
default(int)
resultado.A resposta aceita, no entanto, enquanto funciona, não é a solução ideal IMHO, que não é fornecida aqui. Portanto, estou fornecendo isso em minha própria resposta para o benefício de quem estiver procurando por ele.
O código original do OP era:
É assim que eu escreveria para evitar exceções e fornecer um resultado padrão:
Isso faz com que seja o tipo de retorno da
Max
funçãoint?
, que permite onull
resultado e, em seguida,??
substitui onull
resultado por0
.EDIT
Apenas para esclarecer algo dos comentários, o Entity Framework atualmente não suporta a
as
palavra - chave; portanto, a maneira de escrevê-la ao trabalhar com a EF seria:Como
[TypeOfWorkers]
poderia ser um nome de classe longo e é entediante de escrever, adicionei um método de extensão para ajudar.Isso só alças
int
, mas o mesmo poderia ser feito paralong
,double
ou qualquer outro tipo de valor que você precisa. O uso desse método de extensão é muito simples, basta passar na função seletora e, opcionalmente, incluir um valor a ser usado para null, cujo padrão é 0. Portanto, o acima pode ser reescrito da seguinte maneira:Espero que ajude as pessoas ainda mais.
fonte
DefaultIfEmpty
resposta mais popular só funciona bem quandoMax
não está sendo feita uma avaliação.Select
como intermediário quando vou usar uma função agregada, comoMax
no resultado. Eu também acho (ainda não testei isso) que o SQL gerado usaria uma consulta de subseleção extra fazendo isso, enquanto o meu lidaria apenas com um conjunto vazio retornando nulo. Obrigado pelo voto positivo e feedback! ;)ShoeSize
foi, na verdade, em uma relacionadoUniform
entidade, eu não usarWorkers.Where(x => x.CompanyId == 8).Select(x => x.Uniform).Max(x => x.ShoeSize)
, em vez gostaria apenas de manter toda a avaliação naMax
função:Workers.Where(x => x.CompanyId == 8).Max(x => x.Uniform.ShoeSize)
. Prefiro usar o menor número possível de métodos em minhas consultas para permitir que a EF tenha a maior liberdade para decidir como construir consultas com eficiência. ;-)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 () não retornará nada nesse caso.
Irá gerar InvalidOperationException, pois a fonte não contém elementos.
fonte
InvalidOperationException
se os objetos na lista forem do tipo não anulável: docs.microsoft.com/en-us/dotnet/api/…fonte
Se for Linq to SQL, não gosto de usar,
Any()
pois resulta em várias consultas ao SQL Server.Se
ShoeSize
não for um campo anulável, usar apenas o.Max(..) ?? 0
não funcionará, mas o seguinte:Absolutamente não altera o SQL emitido, mas retorna 0 se a sequência estiver vazia porque altera o
Max()
retorno de um emint?
vez de umint
.fonte
(supondo que
ShoeSize
seja do tipoint
)Se
Workers
for umDbSet
ouObjectSet
do Entity Framework, sua consulta inicial geraria umaInvalidOperationException
, mas não reclamaria de uma sequência vazia, mas reclamaria que o valor materializado NULL não pode ser convertido em umaint
.fonte
Max lançará System.InvalidOperationException "Sequence contém nenhum elemento"
fonte
Nota: a consulta com
DefaultIfEmpty()
pode ser significativamente mais lenta . No meu caso, isso foi uma consulta simples com.DefaultIfEmpty(DateTime.Now.Date)
.Eu estava com preguiça de criar um perfil, mas obviamente a EF tentou obter todas as linhas e, em seguida, pegar o
Max()
valor.Conclusão: às vezes o manuseio
InvalidOperationException
pode ser a melhor escolha.fonte
Você pode usar um ternário interno
.Max()
para manipular o predicado e definir seu valor;Você precisaria manipular a
Workers
coleção como nula / vazia, se for possível, mas isso dependerá da sua implementação.fonte
Você pode tentar isso:
fonte
Você pode verificar se há trabalhadores antes de executar o Max ().
fonte