2011-04-06 23 views
17

¿Cómo puedo actualizar una sola propiedad de un registro sin recuperarlo primero? lo que pido en el contexto de Código EF Primera 4.1Actualizar una sola propiedad de un registro en Entity Framework Code First

dice que tengo una clase de usuario, la asignación a los usuarios de la tabla en la base de datos:

class User 
{ 
    public int Id {get;set;} 
    [Required] 
    public string Name {get;set;} 
    public DateTime LastActivity {get;set;} 
    ... 
} 

Ahora quiero actualizar LastActivity de un usuario. Tengo identificación de usuario. Puedo hacerlo fácilmente consultando el registro del usuario, establezco un nuevo valor en LastActivity y luego llamo a SaveChanges(). Pero esto daría lugar a una consulta redundante.

Me muero usando el método Attach. Pero debido a que EF arroja una excepción de validación en Nombre si es nula, configuro Nombre a una cadena aleatoria (no se actualizará a DB). Pero esto no parece ser una solución elegante:

using (var entities = new MyEntities()) 
{ 
    User u = new User {Id = id, Name="this wont be updated" }; 
    entities.Users.Attach(u); 
    u.LastActivity = DateTime.Now; 
    entities.SaveChanges(); 
} 

Estaría muy appriciate si alguien me puede proporcionar una mejor solución. Y perdónenme por cualquier error ya que esta es la primera vez que hago una pregunta sobre SO.

Respuesta

35

Este es un problema de la aplicación de validación. La validación solo puede validar una entidad completa. No valida solo las propiedades modificadas como se esperaba. Debido a que la validación se debe apagar en escenarios en los que desea utilizar objetos ficticios incompletas:

using (var entities = new MyEntities()) 
{ 
    entities.Configuration.ValidateOnSaveEnabled = false; 

    User u = new User {Id = id, LastActivity = DateTime.Now }; 
    entities.Users.Attach(u); 
    entities.Entry(user).Property(u => u.LastActivity).IsModified = true; 
    entities.SaveChanges(); 
} 

Esto es obviamente un problema si desea utilizar el mismo contexto para la actualización de los objetos ficticios y para la actualización de toda entidades donde se debe usar la validación La validación tiene lugar en SaveChanges por lo que no puede decir qué objetos deben validarse y cuáles no.

+0

Estaba buscando una forma de desactivar la validación al guardar, pero no pude. Gracias por la solución. –

+0

Este problema_se debe solucionar en EF 5. –

+0

Me gustaría señalar que algo llamado comprobación de concurrencia podría causar una excepción de "0 filas actualizadas" porque agregará una marca en la cláusula where para hacer coincidir la columna rowversion. (que en mi caso fue nulo porque era un stub) – Slight

3

Usted puede tratar de una especie de truco:
context.Database.ExecuteSqlCommand("update [dbo].[Users] set [LastActivity] = @p1 where [Id] = @p2",
new System.Data.SqlClient.SqlParameter("p1", DateTime.Now),
new System.Data.SqlClient.SqlParameter("p2", id));

+0

Eso no es un truco. Sin embargo, lo desafortunado es que las actualizaciones directas de una sola columna solo se pueden realizar con toda la entidad en la mano y mediante una cadena SQL sin formato como esta. –

4

Actualmente estoy lidiando con esto ahora mismo. Lo que decidí hacer fue anular el método ValidateEntity en el contexto DB.

protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items) 
{ 
    var result = base.ValidateEntity(entityEntry, items); 

    var errors = new List<DbValidationError>(); 

    foreach (var error in result.ValidationErrors) 
    { 
     if (entityEntry.Property(error.PropertyName).IsModified) 
     { 
      errors.Add(error); 
     } 
    } 

    return new DbEntityValidationResult(entityEntry, errors); 
} 

estoy seguro de que hay algunos agujeros que pueden ser golpe en ella, pero parecía mejor que las alternativas.

+1

Esto no es un código completo pero me gusta la idea. El principal problema con el código es que caerá en una situación en la que la propiedad que intenta ver no la modifica, ya sea un tipo primitivo o complejo, y se bloqueará. Necesita tener una condición para Referencia o Colección. –

Cuestiones relacionadas