Update a single property of a record in Entity Framework Code First

17,703

Solution 1

This is a problem of validation implementation. The validation is able to validate only a whole entity. It doesn't validate only modified properties as expected. Because of that the validation should be turned off in scenarios where you want to use incomplete dummy objects:

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();
}

This is obviously a problem if you want to use the same context for update of dummy objects and for update of whole entities where the validation should be used. The validation take place in SaveChanges so you can't say which objects should be validated and which don't.

Solution 2

I'm actually dealing with this right now. What I decided to do was override the ValidateEntity method in the DB context.

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);
} 

I'm sure there's some holes that can be poked in it, but it seemed better than the alternatives.

Solution 3

You can try a sort of hack:
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));

Share:
17,703

Related videos on Youtube

Quang Vo
Author by

Quang Vo

Updated on May 27, 2022

Comments

  • Quang Vo
    Quang Vo almost 2 years

    How can I update a single property of a record without retrieving it first? I'm asking in the context of EF Code First 4.1

    Says I have a class User, mapping to table Users in Database:

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

    Now I want to update LastActivity of a user. I have user id. I can easily do so by querying the user record, set new value to LastActivity, then call SaveChanges(). But this would result in a redundant query.

    I work around by using Attach method. But because EF throws a validation exception on Name if it's null, I set Name to a random string (will not be updated back to DB). But this doesn't seem a elegant solution:

    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();
    }
    

    I would be very appriciate if someone can provide me a better solution. And forgive me for any mistake as this is the first time I've asked a question on SO.

  • Quang Vo
    Quang Vo about 13 years
    I was looking for a way to disable validation on saving, but wasn't able to. Thank you for the solution.
  • Peter Smith
    Peter Smith over 10 years
    This problem seems to be fixed in EF 5.
  • Slight
    Slight almost 9 years
    I'd like to point out that something called concurrency checking could cause a "0 rows updated" exception because it will be adding a check in the where clause to match the rowversion column. (which in my case was null because it was a stub)
  • Patrick Desjardins
    Patrick Desjardins over 8 years
    This is not a complete code but I like the idea. The main problem with the code is that you will fall into situation where the property that you try to see that is modified it not a primitive or a complex type, an thus will crash. You need to have a condition for Reference or Collection.
  • dan
    dan over 8 years
    Can we do the same but use a different field other than 'Id'? e.g. User u = new User {Email = "[email protected]", LastActivity = DateTime.Now }; where Email == "[email protected]" can uniquely identify a entity.
  • MikeW
    MikeW almost 8 years
    How would this be used to update a navigation property?
  • Nicholas Petersen
    Nicholas Petersen over 7 years
    That's not a hack. What is unfortunate though is that direct updates of a single column can only be done with the whole entity in hand and through a raw SQL string like this.