EF Core Change Tracking
Qué es Change Tracking
EF Core utiliza el Change Tracker para detectar qué entidades y qué propiedades han cambiado mientras están asociadas a un DbContext. Esta información se usa para generar los INSERT, UPDATE y DELETE correctos cuando se ejecuta SaveChanges.
DbContext y ciclo de vida
El Change Tracker vive dentro del DbContext.
- Mientras el DbContext esté vivo, las entidades pueden ser trackeadas.
- Al disponer el DbContext, se pierde todo el tracking.
- ChangeTracker.Clear() elimina todas las entidades trackeadas.
Usar DbContexts de corta duración es la práctica recomendada.
Estados de una entidad
Cada entidad trackeada tiene un estado:
- Detached: la entidad no es conocida por el DbContext.
- Added: la entidad se insertará en la base de datos.
- Unchanged: la entidad no ha cambiado.
- Modified: la entidad tiene cambios pendientes.
- Deleted: la entidad será eliminada.
EF Core decide qué operación SQL ejecutar según este estado.
Tracking a nivel de propiedad
EF Core no solo trackea entidades, también trackea propiedades.
- Solo las propiedades marcadas como Modified se incluyen en el UPDATE.
- Si ninguna propiedad está marcada como modificada, no se ejecuta ningún UPDATE.
Esto permite actualizaciones parciales de forma natural.
Cómo una entidad pasa a estar trackeada
Una entidad queda trackeada cuando:
- Se obtiene mediante una consulta normal (sin AsNoTracking).
- Se adjunta explícitamente usando Attach, Add o Update.
- Se agrega como parte de un grafo de entidades relacionadas.
Una entidad con AsNoTracking nunca queda trackeada automáticamente.
AsNoTracking
AsNoTracking indica a EF Core que no realice seguimiento de las entidades devueltas.
- Mejora rendimiento en escenarios de solo lectura.
- No permite detectar ni guardar cambios.
- No se puede usar Entry().Property().IsModified sin antes adjuntar la entidad.
Detección de cambios
Por defecto EF Core usa una estrategia basada en snapshots:
- Guarda una copia de los valores originales al cargar la entidad.
- Compara los valores actuales con los originales al ejecutar SaveChanges.
La detección de cambios ocurre automáticamente antes de SaveChanges, pero se puede forzar con ChangeTracker.DetectChanges().
Notificación de cambios
Opcionalmente, EF Core puede detectar cambios mediante notificaciones:
- INotifyPropertyChanged
- INotifyPropertyChanging
Esto evita el uso de snapshots y puede mejorar rendimiento en escenarios avanzados, pero aumenta la complejidad del modelo.
Métodos Attach, Update y Add
- Attach: adjunta la entidad como Unchanged.
- Add: marca la entidad como Added.
- Update: marca la entidad y todas sus propiedades como Modified.
Update es equivalente a un PUT agresivo y debe usarse solo con entidades completas.
Riesgo de sobrescritura (Lost Update)
Usar Update con entidades parciales puede sobrescribir cambios hechos por otros procesos sin lanzar errores. Esto es especialmente peligroso en escenarios concurrentes como colas, workers y APIs.
Conclusión clave
EF Core no entiende PUT ni PATCH. La diferencia está en cómo el desarrollador modifica las entidades antes de SaveChanges. Change Tracking es potente, pero mal usado puede causar pérdida silenciosa de datos.