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


119

Estou tendo um trabalho danado para encontrar uma comparação das diferentes maneiras de consultar um único item e quando usar cada uma.

Alguém tem um link que compare tudo isso, ou uma explicação rápida de por que você usaria um em vez do outro? Existem ainda mais operadoras que eu não conheço?

Obrigado.

Respostas:


205

Aqui está uma visão geral dos diferentes métodos:

  • Find () - quando você deseja obter um item pela chave primária. Isso retornará nulo se não puder encontrar um item. Ele examinará o contexto antes de ir para o banco de dados (conforme apontado por Yaron nos comentários), o que pode ser um fator de eficiência importante se você precisar obter a mesma entidade várias vezes enquanto o mesmo contexto estiver ativo.

  • Single () - quando você espera que exatamente um item seja retornado por uma consulta. Isso lançará uma exceção se a consulta não retornar exatamente um item.

  • SingleOrDefault () - quando você espera que zero ou um item seja retornado por uma consulta (ou seja, você não tem certeza se existe um item com uma determinada chave). Isso lançará uma exceção se a consulta não retornar zero ou um item.

  • First () - quando você espera que um ou mais itens sejam retornados por uma consulta, mas deseja acessar apenas o primeiro item em seu código (a ordem pode ser importante na consulta aqui). Isso lançará uma exceção se a consulta não retornar pelo menos um item.

  • FirstOrDefault () - quando você espera que zero ou mais itens sejam retornados por uma consulta, mas você deseja acessar apenas o primeiro item em seu código (ou seja, você não tem certeza se existe um item com uma determinada chave)


1
Depende do cenário. Se você sabe que sempre deve obter um único registro de volta do banco de dados, nem mais, nem menos, para uma determinada consulta, Single () é o 'certo' para usar. Em outras situações, os outros podem ser mais apropriados. Nas versões anteriores do EF estávamos limitados a First () e FirstOrDefault (), que funcionam para cenários onde você está esperando um único registro, mas eles não irão avisá-lo se você realmente receber mais do que aquele único registro de volta, o que pode ser importante dependendo de a situação.
Steve Willcock

1
Obrigado. Não consigo mais me ver precisando de First (), onde Single () não seria melhor. Se eu fosse menos denso, tenho certeza de que poderia apreciar / entender quando usar o First () ainda.
asfsadf

1
First () faz mais sentido no caso em que você deseja recuperar apenas o objeto com o maior ou o menor valor pelo qual você está ordenando. Por exemplo, encontre-me a venda com o maior valor total. Sales.OrderByDescending(s => s.TotalValue).First();
Mike Chamberlain de

5
Todos os comentários parecem uma diferença importante. Find () é o único método que pesquisa o contexto antes de acessar o banco de dados.
Yaron Levi

5
Outro ponto é ao consultar um banco de dados sql, Singleou SingleOrDefaultconsultará 2 registros (limite 2) enquanto Firstou FirstOrDefaultconsultará 1 (limite 1).
Bart Calixto

22

Eu sempre costumo usar FirstOrDefault. Se você realmente deseja ser exigente com o desempenho, deve usar FirstOrDefaultno EF. Under the covers SingleOrDefaultusa top (2) na consulta porque, ele precisa verificar se há uma segunda linha que corresponde aos critérios e, se isso acontecer, ele lança uma exceção. Basicamente, SingleOrDefaultvocê está dizendo que deseja lançar uma exceção se sua consulta retornar mais de 1 registro.


5
Você já mediu a diferença de desempenho entre FirstOrDefaulte SingleOrDefaultpara ser significativa? Eu diria que é uma otimização prematura na maioria dos casos.
Steven

Tenho a tendência de usar Single()ou SingleOrDefault()quando devolvo algo do qual deveria existir apenas um . A razão de eu fazer isso é para detectar bugs fazendo consultas mal escritas, que retornam mais do que deveriam, falham. Pelo menos na minha opinião, isso ajudará a manter os dados do sistema consistentes. Claro que isso é mais lento, mas acho que não é muito mais lento, e estou disposto a pagar esse preço.
mortb

15

É realmente muito simples: Singleretorna um único item e lança uma exceção se não houver nenhum ou mais de um item. Firstdevolverá o primeiro item ou jogará quando não houver item. FirstOrDefaultirá retornar o primeiro item ou retornar o valor padrão (que é nullno caso de o tipo fornecido ser um tipo de referência) quando não houver item.

Este é o comportamento que a API deve ter. Observe, entretanto, que a implementação subjacente pode ter um comportamento diferente. Embora o Entity Framework obedeça a isso, um O / RM como LLBLGen também pode retornar nullao chamar, o Firstque é uma coisa muito estranha. Esta foi uma decisão muito estranha (e teimosa) do designer IMO.


Obrigado Steven. Acho que ainda estou me perguntando por que você usaria um em vez do outro. Sempre usei FirstOrDefault () e estava curioso para saber por que muitos dos novos exemplos que vi mudaram para Single (). Existe um motivo para mudar para Simples ()? Existem outros que também realizam a mesma coisa, que eu deveria considerar?
asfsadf de

7
Se você gosta que seu código "falhe rápido", First () e Single () permitem que seu código diga mais precisamente o que é esperado (para que ele possa falhar de outra forma)
Frank Schwieterman

3
Eu concordo totalmente com o Frank. Também se trata de comunicar a intenção. Singleexpressa claramente que você espera que o resultado tenha apenas um elemento.
Steven de

8

Cada um dos quatro métodos tem seu lugar; Embora você realmente tenha apenas duas operações diferentes.

  • Primeiro - esperando um conjunto de resultados que contém vários itens, forneça o primeiro item desse conjunto.
  • Único - Esperando um único resultado de volta, me dê esse item.

A versão xxxxOrDefault () apenas adiciona "Não quero considerar um conjunto de resultados vazio uma circunstância excepcional."


OK, então me parece que o First () raramente seria útil. Estou tendo dificuldade em pensar em um cenário em que Single () não seja a primeira opção. Você tem uma mão rápida, por acaso? Obrigado.
asfsadf de

3
Infelizmente, muitos desenvolvedores usam First () ou FirstOrDefault () puramente como uma medida defensiva, pensando que evitará uma exceção quando na verdade tem apenas o potencial de ocultar problemas reais.
Matt H

3

Por outro lado, você pode dividir esses métodos pela lógica central, assim:

  • O método consultará o banco de dados diretamente : Single (), SingleOrDefault (), First (), FirstOrDefault ()
  • O método realizará uma pesquisa no cache antes mesmo de emitir a consulta no banco de dados : Find ()

Para alguns detalhes de desempenho, especialmente no segundo caso, você pode olhar aqui: https://msdn.microsoft.com/en-us/data/hh949853.aspx?f=255&MSPPError=-2147217396#3

Além disso, no primeiro grupo você pode definir consultas complexas, mas com o método Find () você pode fornecer apenas a chave de entidade para pesquisa.


0

Single () e SingleOrDefault () são normalmente usados ​​em identificadores únicos, como IDs, enquanto First () ou FirstOrDefault () geralmente são usados ​​para uma consulta que pode ter vários resultados, mas você deseja apenas o "Top 1" .

Single () ou First () lançaria uma exceção se nenhum resultado fosse retornado, SingleOrDefault () e FirstOrDefault () capturariam a exceção e retornaria nulo ou padrão (ResultDataType).

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.