¿Qué diferencia hace .AsNoTracking ()?

228

Tengo una pregunta con respecto a la .AsNoTracking()extensión, ya que todo esto es bastante nuevo y bastante confuso.

Estoy usando un contexto por solicitud para un sitio web.

Muchas de mis entidades no cambian, por lo que no es necesario realizar un seguimiento, pero tengo el siguiente escenario en el que no estoy seguro de qué va a la base de datos, o incluso si hace una diferencia en este caso.

Este ejemplo es lo que estoy haciendo actualmente:

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

Esto es lo mismo que arriba pero eliminando el .AsNoTracking()Paso 1:

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

Los pasos 1 y 2 usan el mismo contexto pero ocurren en momentos diferentes. Lo que no puedo resolver es si hay alguna diferencia. Como el Paso 2 es una actualización, supongo que ambos llegarán a la base de datos dos veces de todos modos.

¿Alguien puede decirme cuál es la diferencia?

dotnetnoob
fuente

Respuestas:

187

La diferencia es que, en el primer caso, el usuario recuperado no es rastreado por el contexto, por lo que cuando vaya a guardar el usuario nuevamente en la base de datos, debe adjuntarlo y establecer el estado correcto del usuario para que EF sepa que debe actualizar el usuario existente en lugar de insertar uno nuevo. En el segundo caso, no necesita hacer eso si carga y guarda al usuario con la misma instancia de contexto porque el mecanismo de seguimiento lo maneja por usted.

Ladislav Mrnka
fuente
1
¿Podemos obtener los mismos beneficios para las clases anónimas en la consulta de selección, como context.Users.Select (u => new {Name = u.Name})? Gracias.
Dilhan Jayathilake
66
@DilhanJayathilake: las clases anónimas no representan a la entidad en sí, por lo que no tienen seguimiento.
Ladislav Mrnka
1
Dado que EF6 infiere la clave de entidad de forma incorrecta en una Vista a veces, AsNoTracking () ignora la clave y, por lo tanto, es una alternativa a la fijación manual de la clave (suponiendo que no se necesitan otros beneficios de la clave).
crokusek
44
También tenga en cuenta que el mayor efecto que tiene AsNoTracking es que la carga diferida no funcionará
Douglas Gaskell
170

ver esta página Entity Framework y AsNoTracking

Lo que hace AsNoTracking

Entity Framework expone una serie de opciones de ajuste de rendimiento para ayudarlo a optimizar el rendimiento de sus aplicaciones. Una de estas opciones de ajuste es .AsNoTracking(). Esta optimización le permite decirle que Entity Frameworkno rastree los resultados de una consulta. Esto significa que Entity Frameworkno realiza ningún procesamiento o almacenamiento adicional de las entidades que devuelve la consulta. Sin embargo, también significa que no puede actualizar estas entidades sin volver a asociarlas al gráfico de seguimiento.

Se pueden obtener importantes ganancias de rendimiento al usar AsNoTracking

Moji
fuente
11
Parece que las ganancias pueden ser contrarrestadas a veces: stackoverflow.com/questions/9259480/…
Fabrice
3
Mi ganancia de rendimiento con una consulta compleja cargando una relación padre-hijo con incluir en un paso fue aproximadamente del 50%
Karl
53

Sin seguimiento de consultas LINQ to Entities

Se recomienda el uso de AsNoTracking () cuando su consulta está destinada a operaciones de lectura. En estos escenarios, recupera sus entidades, pero su contexto no las rastrea, lo que garantiza un uso mínimo de memoria y un rendimiento óptimo.

Pros

  1. Rendimiento mejorado sobre consultas regulares de LINQ.
  2. Objetos totalmente materializados.
  3. Más simple de escribir con sintaxis integrada en el lenguaje de programación.

Contras

  1. No apto para operaciones CUD.
  2. Ciertas restricciones técnicas, como: Los patrones que usan DefaultIfEmpty para consultas OUTER JOIN dan como resultado consultas más complejas que las simples instrucciones OUTER JOIN en Entity SQL.
  3. Aún no puede usar LIKE con la coincidencia de patrones generales.

Más información disponible aquí:

Consideraciones de rendimiento para Entity Framework

Entity Framework y NoTracking

Referencia nula
fuente
10

AsNoTracking () permite omitir el requisito de "clave única por registro" en EF (no mencionado explícitamente por otras respuestas).

Esto es extremadamente útil cuando se lee una Vista que no admite una clave única porque quizás algunos campos son anulables o la naturaleza de la vista no es indexable lógicamente.

Para estos casos, la "clave" se puede establecer en cualquier columna no anulable, pero luego se debe utilizar AsNoTracking () con cada consulta que se omita (duplicados por clave).

crokusek
fuente
2
Solo para reiterar la importancia de esto con Vistas, tengo una consulta desde una vista que devuelve 7 registros únicos cuando se ejecuta a través de SSMS. Cuando se ejecuta a través de EF, sin el modificador AsNoTracking, obtengo el primer registro, tres copias del segundo y tres copias del tercero. Esto tomó muchos incrédulos rascarse la cabeza para solucionarlo, ¡y estaba usando AsNoTracking que lo solucionó!
Ade
Tuve exactamente el mismo problema al usar Linq to Entities mientras consultaba una vista sin claves principales. Solo descubrí AsNoTracking después de medio día de rascarse la cabeza. Esta publicación del foro ASP.Net finalmente me llevó a ella. forums.asp.net/t/…
red_dorian
6

Si tiene algo más que altere la base de datos (por ejemplo, otro proceso) y necesita asegurarse de ver estos cambios, use AsNoTracking() , de lo contrario EF puede darle la última copia que tuvo su contexto, por lo tanto, es bueno usar un nuevo contexto en cada consulta :

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

Andrew Paté
fuente