Considere os métodos de extensão IEnumerable SingleOrDefault()
eFirstOrDefault()
Documentos MSDN queSingleOrDefault
:
Retorna o único elemento de uma sequência ou um valor padrão se a sequência estiver vazia; esse método lança uma exceção se houver mais de um elemento na sequência.
enquanto que FirstOrDefault
a partir da MSDN (presumivelmente quando se utiliza um OrderBy()
ou OrderByDescending()
ou nenhuma),
Retorna o primeiro elemento de uma sequência
Considere algumas consultas de exemplo, nem sempre é claro quando usar esses dois 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?
Questão
Quais convenções você segue ou sugere ao decidir usar SingleOrDefault()
e FirstOrDefault()
em suas consultas LINQ?
fonte
Se o seu conjunto de resultados retornar 0 registros:
SingleOrDefault
retorna o valor padrão para o tipo (por exemplo, o padrão para int é 0)FirstOrDefault
retorna o valor padrão para o tipoSe o conjunto de resultados retornar 1 registro:
SingleOrDefault
retorna esse registroFirstOrDefault
retorna esse registroSe o seu conjunto de resultados retornar muitos registros:
SingleOrDefault
lança uma exceçãoFirstOrDefault
retorna o primeiro registroConclusão:
Se você deseja que uma exceção seja lançada se o conjunto de resultados contiver muitos registros, use
SingleOrDefault
.Se você deseja sempre 1 registro, independentemente do conjunto de resultados, use
FirstOrDefault
fonte
FirstOrDefault
é retornado o primeiro registro significa novo registro (último) / registro antigo (primeiro)? u pode me esclarecer?Há sim
entre os dois.
Diferença semântica:
FirstOrDefault
retorna um primeiro item de potencialmente múltiplo (ou padrão, se não houver nenhum).SingleOrDefault
assume que existe um único item e o devolve (ou o padrão, se não houver). Vários itens são uma violação do contrato, uma exceção é lançada.Diferença de desempenho
FirstOrDefault
geralmente é mais rápido, itera até encontrar o elemento e precisa iterar todo o enumerável quando não o encontra. Em muitos casos, há uma alta probabilidade de encontrar um item.SingleOrDefault
precisa verificar se existe apenas um elemento e, portanto, sempre itera todo o enumerável. Para ser preciso, ele itera até encontrar um segundo elemento e gerar uma exceção. Mas na maioria dos casos, não há segundo elemento.Conclusão
Use
FirstOrDefault
se você não se importa com quantos itens existem ou quando não pode verificar a exclusividade (por exemplo, em uma coleção muito grande). Quando você verifica a exclusividade ao adicionar os itens à coleção, pode ser muito caro verificá-lo novamente ao procurar esses itens.Use
SingleOrDefault
se você não precisa se preocupar muito com o desempenho e deseja garantir que a suposição de um único item seja clara para o leitor e verificada em tempo de execução.Na prática, você usa
First
/FirstOrDefault
frequentemente mesmo nos casos em que assume um único item, para melhorar o desempenho. Você ainda deve se lembrar queSingle
/SingleOrDefault
pode melhorar a legibilidade (porque afirma a suposição de um único item) e a estabilidade (porque a verifica) e usá-lo adequadamente.fonte
SingleOrDefault
de vários objetos ao usar o Linq to Objects, mas nãoSingleOrDefault
precisa iterar no máximo 2 itens se o Linq estiver falando com um banco de dados, por exemplo? Basta saber ..Enumerable
.Ninguém mencionou que o FirstOrDefault traduzido no SQL faz o registro TOP 1 e o SingleOrDefault faz o TOP 2, porque é necessário saber se há mais de um registro.
fonte
FirstOrDefault()
adicionaLIMIT 0,1
enquantoSingleOrDefault()
nada acrescenta.Para LINQ -> SQL:
SingleOrDefault
FirstOrDefault
fonte
Eu uso
SingleOrDefault
em situações em que minha lógica determina que o resultado será zero ou um. Se houver mais, é uma situação de erro, o que é útil.fonte
SingleOrDefault: você está dizendo que "No máximo" há um item que corresponde à consulta ou padrão FirstOrDefault: Você está dizendo que há "Pelo menos" um item que corresponde à consulta ou padrão
Diga isso em voz alta na próxima vez que precisar escolher e provavelmente deverá escolher sabiamente. :)
fonte
FirstOrDefault. More correctly:
FirstOrDefault` = Qualquer número de resultados, mas eu me preocupo apenas com o primeiro, também pode não haver resultados.SingleOrDefault
= Existem 1 ou 0 resultados, se houver mais, significa que há um erro em algum lugar.First
= Há pelo menos um resultado e eu quero.Single
= Existe exatamente 1 resultado, nem mais, nem menos, e eu quero esse.Nos seus casos, eu usaria o seguinte:
selecione por ID == 5: não há problema em usar SingleOrDefault aqui, porque você espera uma entidade [ou nenhuma], se você tiver mais de uma entidade com o ID 5, há algo errado e definitivamente uma exceção digna.
ao procurar pessoas cujo primeiro nome seja igual a "Bobby", pode haver mais de um (possivelmente eu pensaria); portanto, você não deve usar Único nem Primeiro, basta selecionar com a operação Onde (se "Bobby" retornar muitos entidades, o usuário precisa refinar sua pesquisa ou escolher um dos resultados retornados)
a ordem pela data de criação também deve ser executada com uma operação Where (é improvável que tenha apenas uma entidade, a classificação não seria muito útil;) no entanto, isso implica que você deseja que TODAS as entidades sejam classificadas - se você quiser apenas UMA, use FirstOrDefault, Single jogaria toda vez se você tivesse mais de uma entidade.
fonte
Ambos são os operadores do elemento e são usados para selecionar um único elemento de uma sequência. Mas há uma pequena diferença entre eles. O operador SingleOrDefault () lançaria uma exceção se mais de um elemento fosse atendido, a condição em que FirstOrDefault () não lançará nenhuma exceção para o mesmo. Aqui está o exemplo.
fonte
No seu último exemplo:
Sim. Se você tentar usar
SingleOrDefault()
e a consulta resultar em mais do que registro, você obteria uma exceção. O único momento em que você pode usar com segurançaSingleOrDefault()
é quando espera apenas 1 e apenas 1 resultado ...fonte
Então, como eu entendo agora,
SingleOrDefault
será bom se você estiver consultando dados que são garantidos como únicos, ou seja, aplicados por restrições de banco de dados, como chave primária.Ou existe uma maneira melhor de consultar a chave primária.
Supondo que minha TableAcc tenha
e eu quero consultar um
AccountNumber 987654
, eu usofonte
Na minha opinião,
FirstOrDefault
está sendo muito usado em demasia. Na maioria dos casos, ao filtrar dados, você espera recuperar uma coleção de elementos que correspondam à condição lógica ou um único elemento único por seu identificador exclusivo - como usuário, livro, publicação etc. por que podemos chegar ao ponto de dizer queFirstOrDefault()
é um cheiro de código, não porque há algo errado com ele, mas porque está sendo usado com muita frequência. Esta postagem do blog explora o tópico em detalhes. Na maioria das vezes, a IMOSingleOrDefault()
é uma alternativa muito melhor; portanto, preste atenção a esse erro e use o método mais apropriado que represente claramente seu contrato e expectativas.fonte
Uma coisa que está faltando nas respostas ....
Se houver vários resultados, o FirstOrDefault sem um pedido de pode trazer de volta resultados diferentes com base em qual estratégia de índice já foi usada pelo servidor.
Pessoalmente, não suporto ver FirstOrDefault no código porque, para mim, o desenvolvedor não se importava com os resultados. Com um pedido, ele pode ser útil como uma maneira de aplicar o mais recente / o mais antigo. Eu tive que corrigir muitos problemas causados por desenvolvedores descuidados usando o FirstOrDefault.
fonte
Consultei o Google sobre o uso dos diferentes métodos no GitHub. Isso é feito executando uma consulta de pesquisa do Google para cada método e limitando a consulta ao domínio github.com e à extensão de arquivo .cs usando a consulta "site: arquivo github.com: cs ..."
Parece que os métodos First * são mais comumente usados que os métodos Single *.
fonte
Não entendo por que você está usando
FirstOrDefault(x=> x.ID == key)
quando isso pode recuperar resultados muito mais rapidamente se você usarFind(key)
. Se você estiver consultando com a chave Primária da tabela, a regra geral é sempre usarFind(key)
.FirstOrDefault
deve ser usado para coisas predicadas como(x=> x.Username == username)
etc.isso não mereceu voto negativo, pois o cabeçalho da pergunta não era específico para linq no DB ou Linq to List / IEnumerable etc.
fonte
Find()
?