Que diferença faz .AsNoTracking ()?

228

Eu tenho uma pergunta sobre a .AsNoTracking()extensão, pois tudo isso é bastante novo e bastante confuso.

Estou usando um contexto por solicitação para um site.

Muitas das minhas entidades não mudam, portanto, não precisam ser rastreadas, mas tenho o seguinte cenário em que não tenho certeza do que está acontecendo no banco de dados, ou mesmo se isso faz diferença nesse caso.

Este exemplo é o que estou fazendo atualmente:

context.Set<User>().AsNoTracking()
// Step 1) Get user
context.Set<User>()
// Step 2) Update user

É o mesmo que acima, mas remove o .AsNoTracking()da Etapa 1:

context.Set<User>();
// Step 1) Get user
context.Set<User>()
// Step 2) Update user

As etapas 1 e 2 usam o mesmo contexto, mas ocorrem em momentos diferentes. O que não consigo descobrir é se existe alguma diferença. Como a Etapa 2 é uma atualização, acho que ambos atingirão o banco de dados duas vezes.

Alguém pode me dizer qual é a diferença?

dotnetnoob
fonte

Respostas:

187

A diferença é que, no primeiro caso, o usuário recuperado não é rastreado pelo contexto; portanto, quando você salvar o usuário novamente no banco de dados, deve anexá-lo e definir o estado correto do usuário para que a EF saiba que deve atualizar o usuário existente. em vez de inserir um novo. No segundo caso, você não precisa fazer isso se carregar e salvar o usuário com a mesma instância de contexto, porque o mecanismo de rastreamento lida com isso para você.

Ladislav Mrnka
fonte
1
Podemos obter os mesmos benefícios para classes anônimas em consultas selecionadas, como context.Users.Select (u => new {Name = u.Name})? Obrigado.
Dilhan Jayathilake
6
@DilhanJayathilake: Classes anônimas não representam a própria entidade e, portanto, não têm rastreamento.
Ladislav Mrnka
1
Como o EF6 infere incorretamente a chave da entidade em uma Visualização, o AsNoTracking () ignora a chave e, portanto, é uma alternativa para corrigir manualmente a chave (supondo que outros benefícios da chave não sejam necessários).
crokusek
4
Além disso, observe o maior AsNoTracking efeito tem é que o carregamento lento não vai funcionar
Douglas Gaskell
170

consulte esta página Entity Framework e AsNoTracking

O que o AsNoTracking faz

O Entity Framework expõe várias opções de ajuste de desempenho para ajudá-lo a otimizar o desempenho de seus aplicativos. Uma dessas opções de ajuste é .AsNoTracking(). Essa otimização permite que você diga para Entity Frameworknão rastrear os resultados de uma consulta. Isso significa que Entity Frameworknão realiza processamento ou armazenamento adicional das entidades retornadas pela consulta. No entanto, isso também significa que você não pode atualizar essas entidades sem conectá-las novamente ao gráfico de rastreamento.

há ganhos de desempenho significativos a serem obtidos usando o AsNoTracking

Moji
fonte
11
Parece que os ganhos às vezes podem ser contrabalançados: stackoverflow.com/questions/9259480/…
Fabrice
3
Meu ganho de desempenho com uma consulta complexa carregamento de uma relação pai-filho com incluir em uma etapa foi cerca de 50%
Karl
53

Não há consultas de rastreamento de LINQ to Entities

O uso de AsNoTracking () é recomendado quando sua consulta é destinada a operações de leitura. Nesses cenários, você recebe de volta suas entidades, mas elas não são rastreadas pelo seu contexto. Isso garante o uso mínimo de memória e o desempenho ideal

Prós

  1. Desempenho aprimorado em consultas LINQ regulares.
  2. Objetos totalmente materializados.
  3. Mais simples de escrever com sintaxe incorporada na linguagem de programação.

Contras

  1. Não é adequado para operações de CUD.
  2. Certas restrições técnicas, como: Padrões usando DefaultIfEmpty para consultas OUTER JOIN resultam em consultas mais complexas do que simples instruções OUTER JOIN no Entity SQL.
  3. Você ainda não pode usar o LIKE com a correspondência geral de padrões.

Mais informações disponíveis aqui:

Considerações de desempenho para o Entity Framework

Estrutura de entidade e NoTracking

NullReference
fonte
34

Desativar o rastreamento também fará com que seus conjuntos de resultados sejam transmitidos para a memória. Isso é mais eficiente quando você trabalha com grandes conjuntos de dados e não precisa de todo o conjunto de dados de uma só vez.

Referências:

Ronnie Overby
fonte
10

O AsNoTracking () permite que o requisito "chave única por registro" no EF seja ignorado (não mencionado explicitamente por outras respostas).

Isso é extremamente útil ao ler uma Visualização que não suporta uma chave exclusiva, porque talvez alguns campos sejam anuláveis ​​ou a natureza da visualização não seja indexável logicamente.

Nesses casos, a "chave" pode ser definida como qualquer coluna não anulável, mas o AsNoTracking () deve ser usado com todos os outros registros de consulta (duplicados por chave) serão ignorados.

crokusek
fonte
2
Apenas para reiterar a importância disso no Views, tenho uma consulta de um view que retorna 7 registros únicos quando executados via SSMS. Quando executado via EF, sem o modificador AsNoTracking, recebo o primeiro registro, três cópias do segundo e três cópias do terceiro. Foi preciso muito arranhar a cabeça incrédulo para consertar, e estava usando o AsNoTracking que o consertava!
22818 Ade
Eu tive exatamente esse mesmo problema ao usar o Linq to Entities ao consultar uma View sem chaves primárias. Só descobri o AsNoTracking depois de meio dia coçando a cabeça. Esta postagem no fórum do ASP.Net finalmente me levou a isso. forums.asp.net/t/…
red_dorian
6

Se você tiver alguma outra coisa alterando o banco de dados (digamos outro processo) e precisar garantir que você veja essas alterações, use AsNoTracking() ; caso contrário, o EF poderá fornecer a última cópia que seu contexto possuía; portanto, é bom usar um novo contexto a cada consulta :

http://codethug.com/2016/02/19/Entity-Framework-Cache-Busting/

andrew pate
fonte