Entity Framework: ¿por qué establecer explícitamente el estado de la entidad como modificado?
La documentación oficial dice que para modificar una entidad recupero un objeto DbEntityEntry y trabajo con las funciones de propiedad o configuro su estado como modificado. Utiliza el siguiente ejemplo.
Department dpt = context.Departments.FirstOrDefault();
DbEntityEntry entry = context.Entry(dpt);
entry.State = EntityState.Modified;
No entiendo el propósito de la segunda y tercera declaración. Si solicito el marco para una entidad como lo hace la primera declaración y luego modifico POCO como en
dpt.Name = "Blah"
Si luego le pido a EF que SaveChanges(), la entidad tiene un estado MODIFICADO (supongo que mediante seguimiento de instantáneas, esto no es un proxy) y los cambios persisten sin la necesidad de configurar manualmente el estado. ¿Me estoy perdiendo de algo?
En su escenario, de hecho, no es necesario establecer el estado. El propósito del seguimiento de cambios es encontrar que ha cambiado un valor en la entidad adjunta y lo ha puesto en estado modificado. Configurar el estado manualmente es importante en el caso de entidades separadas (entidades cargadas sin seguimiento de cambios o creadas fuera del contexto actual).
Como se dijo, en un escenario con entidades desconectadas puede resultar útil establecer el estado de una entidad en Modified
. Guarda un viaje de ida y vuelta a la base de datos si simplemente adjunta la entidad desconectada, en lugar de buscar la entidad de la base de datos y modificarla y guardarla.
Pero puede haber muy buenas razones para no establecer el estado Modified
(y estoy seguro de que Ladislav estaba al tanto de esto, pero aun así me gustaría señalarlas aquí).
Se actualizarán todos los campos del registro, no solo los cambios. Hay muchos sistemas en los que se auditan las actualizaciones. La actualización de todos los campos provocará una gran cantidad de desorden o requerirá que el mecanismo de auditoría filtre los cambios falsos.
Concurrencia optimista. Dado que todos los campos están actualizados, esto puede causar más conflictos de los necesarios. Si dos usuarios actualizan los mismos registros simultáneamente pero no los mismos campos, no tiene por qué haber un conflicto. Pero si siempre actualizan todos los campos, el último usuario siempre intentará escribir datos obsoletos. En el mejor de los casos, esto provocará una excepción de simultaneidad optimista o, en el peor de los casos, una pérdida de datos.
Actualizaciones inútiles. La entidad se marca como modificada, pase lo que pase. Las entidades sin cambios también activarán una actualización. Esto puede ocurrir fácilmente si las ventanas de edición se pueden abrir para ver detalles y cerrar con
OK
.
Entonces es un buen equilibrio. Reduzca los viajes de ida y vuelta o reduzca la redundancia.
De todos modos, una alternativa para establecer el estado Modified
es (usando DbContext
API):
void UpdateDepartment(Department department)
{
var dpt = context.Departments.Find(department.Id);
context.Entry(dpt).CurrentValues.SetValues(department);
context.SaveChanges();
}
CurrentValues.SetValues
marca propiedades individuales como Modified
.
O adjunte una entidad desconectada y marque las propiedades individuales Modified
manualmente:
context.Entry(dpt).State = System.Data.Entity.EntityState.Unchanged;
context.Entry(dpt).Property(d => d.Name).IsModified = true;