Pregunta 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?


76
2018-06-22 19:03


origen


Respuestas:


Cuando tu lo hagas context.Entry(entity).State = EntityState.Modified;, no solo está uniendo la entidad a DbContext, también estás marcando toda la entidad como sucia. Esto significa que cuando lo haces context.SaveChanges(), EF generará una declaración de actualización que se actualizará todas los campos de la entidad.

Esto no siempre es deseado.

Por otra parte, DbSet.Attach(entity) conecta la entidad al contexto sin marcándolo 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 context.SaveChanges(), EF no generará una actualización de base de datos para esta entidad.

Incluso si planea hacer una actualización a una entidad, si la entidad tiene muchas propiedades (columnas db) pero solo quiere actualizar algunas, puede resultarle ventajoso hacer una DbSet.Attach(entity)y luego solo actualiza las pocas propiedades que necesitan actualización. Hacerlo de esta manera generará una declaración 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 causará que todas las propiedades / columnas se actualicen)

Documentación relevante: Agregar / Adjuntar y Estados de 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 declaración 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 declaración de actualización generada es diferente:

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

Como puede ver, la declaración de actualización solamente 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.


184
2018-06-22 19:24



Cuando usas el DbSet.Update método, Entity Framework marca todas las propiedades de su entidad como EntityState.Modified, así que los sigue. Si desea cambiar solo algunas de sus propiedades, no todas, use DbSet.Attach. Este método hace que todas tus propiedades EntityState.Unchanged, entonces debes hacer tus propiedades que quieras actualizar EntityState.Modified. Por lo tanto, cuando la aplicación llega a DbContext.SaveChanges, solo operará propiedades modificadas.


0
2017-09-15 07:27