Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Attach for Update Entity Framework [duplicate]

I am trying to do an update for a table using EF 5.x using attach. this table has other fields that are required but its an existing row. so i am trying to update without any fetch. userid is the primary key for the table. i am trying to update the status. but it throws an EntityValidationErrors saying password is required which is another required field but not primary key. since this is a update to existing row why do you need to provide the requried fields for update?

    var webUser = new WebUser() { UserId = webUserId, OnlineStatus = (sbyte)status };
    using (var dbxupdate = new xEntities())
    {
        try
        {
            dbxupdate.WebUsers.Attach(webUser);
dbxupdate.Entry(webUser).State = EntityState.Modified;
            dbxupdate.Entry(webUser).Property(x => x.OnlineStatus).IsModified = true;
            dbxupdate.SaveChanges();
        }
        catch (DbEntityValidationException dbEx)
        {
            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                foreach (var validationError in validationErrors.ValidationErrors)
                {
                    Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
                }
            }
        }
    }
like image 937
Justin Homes Avatar asked Dec 31 '12 20:12

Justin Homes


2 Answers

.Attach() is really only useful for updating entities in a detached scenario like this:

User entity = null;

using (var db = new DbContext()) {
    entity = (from p in db.Users
              where p.Id == 1
              select p).FirstOrDefault();

    System.Diagnostics.Trace.WriteLine(entity.Name); //Outputs "Jane Doe"
}

entity.Name = "John Doe" //Modified while no longer connected to database

using (var db = new DbContext()) {
    db.Users.Attach(entity);
    db.Entry(entity).Property(a => a.Name).IsModified = true;
    db.SaveChanges();

    System.Diagnostics.Trace.WriteLine(entity.Name); //Now outputs "John Doe"
}

In your scenario, the entity you're creating isn't being retrieved by its key and the database is treating it as an entirely new entity. I assume that your password is a non-nullable field which then causes EF to throw an error when it attempts to save your changes. If you didn't have any such errors then EF would automatically null out any fields that you didn't modify and then save the entity (which isn't the result you're looking for either).

In order to make the changes that you really want, try something like the following:

using (var db = new DbContext()) {
    db.Users
        .Single(a => (a.Id == 1))
        .OnlineStatus = ((sbyte)status);
    db.SaveChanges();
}

And then add whatever other error handling/validation code that you want. Alternatively you could store the entity in variable for making changes to more than one field at a time. EF should automatically determine which values have been altered and only generate the SQL required to make those changes. Meaning that if you have something like:

using (var db = new DbContext()) {
    foreach (var item in entityList) {
        var entity = db.Users.Single(a => (a.Id == item.Id));

        entity.Name = item.Name;
        entity.Address = item.Address;
    }

    db.SaveChanges();
}

then EF should only update the entities/fields that are actually affected by this code. If the Name or Address stays the same then EF will skip that field for that entity when it saves the changes to the database.

like image 146
Kittoes0124 Avatar answered Oct 04 '22 09:10

Kittoes0124


The entity is validated on save, regardless of whether it was attached or loaded from the database. If you use validation attributes or a validation method, the entity must pass validation to be saved.

If you have a [Required] attribute on the password field I think you are quite stuck. You probably have to load the entity and then update the info instead of just attaching it.

like image 35
Anders Abel Avatar answered Oct 04 '22 11:10

Anders Abel