Attach for Update Entity Framework

ado.net c# entity-framework

Question

Using EF 5.x and attach, I'm attempting to update a table. Other fields in this table are necessary, but they already exist in a row. I'm attempting to update without fetching anything. The table's primary key is userid. I'm attempting to change the status. However, it raises an EntityValidationError stating that the password field, which is another mandatory field, but not the primary key, is required. Why is it necessary to give the necessary fields for updating when this is an update to an existing row?

    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);
                }
            }
        }
    }
1
8
12/31/2012 8:14:02 PM

Accepted Answer

ZZZ_tmp
1
3/24/2018 7:38:55 AM

Popular Answer

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

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 database is treating the entity you're generating as if it were a completely new entity because it can't be retrieved by its key. I'm going to assume that the password you entered is a non-nullable field because of which EF throws an error when it tries to save your changes. If you didn't have any of these problems, EF would automatically null out any fields you hadn't changed before saving the entity, which is also the opposite of what you want.

Try something like the following to make the modifications that you truly want to:

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

After that, add any additional error handling or validation code you desire. Alternately, you might keep the entity in a variable to allow you to alter multiple fields at once. Only the SQL needed to perform those modifications should be generated by EF, which should automatically identify which values have been changed. Consequently, if you possess 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();
}

only those entities and attributes that are truly impacted by this code should be updated by EF. When EF saves the changes to the database, it will skip any fields for that entity whose Name or Address remains unchanged.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow