DbSet.Attach (entidad) vs DbContext.Entry (entidad) .State = EntityState.Modified

Cuando estoy en un escenario separado y obtengo un dto del cliente que mapeo en una entidad para guardarlo, hago esto:

context.Entry(entity).State = EntityState.Modified; context.SaveChanges(); 

Por lo que entonces es el DbSet.Attach(entity)

o ¿por qué debería usar el método .Attach cuando EntityState.Modified ya une la entidad?

Cuando hace context.Entry(entity).State = EntityState.Modified; , no solo estás adjuntando la entidad al DbContext , también estás marcando toda la entidad como sucia. Esto significa que cuando haga context.SaveChanges() , EF generará una statement de actualización que actualizará todos los campos de la entidad.

Esto no siempre es deseado.

Por otro lado, DbSet.Attach(entity) la entidad al contexto sin marcarlo sucio. Es equivalente a hacer context.Entry(entity).State = EntityState.Unchanged;

Al asociar de esta manera, a menos que luego proceda a actualizar una propiedad en la entidad, la próxima vez que llame a context.SaveChanges() , EF no generará una actualización de base de datos para esta entidad.

Incluso si planea realizar una actualización de una entidad, si la entidad tiene muchas propiedades (columnas db) pero solo desea actualizar algunas, puede resultarle ventajoso realizar una DbSet.Attach(entity) y luego solo actualice las pocas propiedades que necesitan actualización. Hacerlo de esta manera generará una statement de actualización más eficiente de EF. EF solo actualizará las propiedades que modificó (en contraste con context.Entry(entity).State = EntityState.Modified; que hará que todas las propiedades / columnas se actualicen)

Documentación relevante: Agregar / Adjuntar y Estados de la entidad .

Ejemplo de código

Digamos que tienes la siguiente entidad:

 public class Person { public int Id { get; set; } // primary key public string FirstName { get; set; } public string LastName { get; set; } } 

Si su código se ve así:

 context.Entry(personEntity).State = EntityState.Modified; context.SaveChanges(); 

El SQL generado se verá más o menos así:

 UPDATE person SET FirstName = 'whatever first name is', LastName = 'whatever last name is' WHERE Id = 123; -- whatever Id is. 

Observe cómo la statement de actualización anterior actualizará todas las columnas, independientemente de si ha cambiado los valores o no.

Por el contrario, si su código usa el adjunto “normal” como este:

 context.People.Attach(personEntity); // State = Unchanged personEntity.FirstName = "John"; // State = Modified, and only the FirstName property is dirty. context.SaveChanges(); 

Entonces la statement de actualización generada es diferente:

 UPDATE person SET FirstName = 'John' WHERE Id = 123; -- whatever Id is. 

Como puede ver, la statement de actualización solo actualiza los valores que en realidad fueron cambiados después de adjuntar la entidad al contexto. Dependiendo de la estructura de su mesa, esto puede tener un impacto positivo en el rendimiento.

Ahora, qué opción es mejor para usted depende completamente de lo que está tratando de hacer.

Cuando utiliza el método DbSet.Update , Entity Framework marca todas las propiedades de su entidad como EntityState.Modified , por lo que las rastrea. Si desea cambiar solo algunas de sus propiedades, no todas, use DbSet.Attach . Este método hace que todas sus propiedades EntityState.Unchanged , por lo que debe hacer que sus propiedades que desea actualizar EntityState.Modified . Por lo tanto, cuando la aplicación DbContext.SaveChanges a DbContext.SaveChanges , solo operará las propiedades modificadas.