8

I have this entity, want to update using entityframework

 EmployeeModel employee = new EmployeeModel
    {
        Id = 1000, //This one must 
        FirstName = modifiedValue,
        Email = modifiedValue, 
        LastName = originalValue,
        Phone = originalValue
    };

Code to update

_db.ObjectStateManager.ChangeObjectState(employee, EntityState.Modified);  
_db.SaveChanges();

This is the SQL statement got once updated

Update Employee set Id=1138,FirstName='modifiedValue',Email='modifiedValue',LastName= 'OriginalValue',phone='originalValue' where Id=1138

But I am expecting this

Update Employee set FirstName='modifiedValue', Email='modifiedValue' where Id=1138.

I dont know what I am missing here. Please let me know.

sivaL
  • 1,812
  • 5
  • 21
  • 30
  • Possible duplicate http://stackoverflow.com/questions/3642371/how-to-update-only-one-field-using-entity-framework – zs2020 Jan 31 '13 at 14:56
  • Sza, That post only one field updated. – sivaL Jan 31 '13 at 15:05
  • You can extend it to update multiple fields following the idea posted in that question. – zs2020 Jan 31 '13 at 15:06
  • Its more focused on Individual property level. My model might have more number of properties. In that case, I want to attach the changed model and do the updates. – sivaL Jan 31 '13 at 16:02

3 Answers3

14

This problem is common when dealing with DTOs. An employee entity is fetched from the database, mapped to a DTO and sent over the wire. The client then modifies this DTO and sends it back to the server.

When you touch (set) a property on an EF entity, EF will assume that the value has been changed. Even if the old value and the new value are exactly the same. The same problem occurs when you map the DTO to a new Entity and attach it to EF and updating its status to 'Modified'.

Using AutoMapper:

// This will result in the full update statement
var employee = AutoMapper.Mapper.Map<EmployeeDto, Employee>(dto);

// This will result in a smaller update statement (only actual changes)
var employee = dbContext.Employees.Find(dto.Id);
AutoMapper.Mapper.Map(dto, employee);

Or, manually (I would avoid doing this, but just for the sake of completeness):

// This will result in a smaller update statement (only actual changes)
var employee = dbContext.Employees.Find(dto.Id);
if (employee.Email != dto.Email )
    employee.Email = dto.Email;

There are probably some other ways for dealing with this problem... but using AutoMapper together with Entity Framework correctly is definitely one of the easiest ways.

deherch
  • 659
  • 4
  • 9
6

This is the solution I got

 var entity = _db.CreateObjectSet<Employee>();
 entity.Detach(employee);
 entity.Attach(employee);

 foreach (string modifiedPro in employeeModel.ModifiedProperties){
  _db.ObjectStateManager.GetObjectStateEntry(employee).SetModifiedProperty(modifiedPro);}

  _db.SaveChanges();

Only modified values in the sql update statement

Update Employee set FirstName='modifiedValue', Email='modifiedValue' where Id=1138.

If anybody knows better answer than this, Please post your suggestions

sivaL
  • 1,812
  • 5
  • 21
  • 30
0

You can try this way

public update(Person model)
{
    // Here model is model return from form on post
    var oldobj = db.Person.where(x=>x.ID = model.ID).SingleOrDefault();

    var UpdatedObj = (Person) Entity.CheckUpdateObject(oldobj, model);

    db.Entry(oldobj).CurrentValues.SetValues(UpdatedObj);
}

public static object CheckUpdateObject(object originalObj, object updateObj)
{
   foreach (var property in updateObj.GetType().GetProperties())
   {
      if (property.GetValue(updateObj, null) == null)
      {
         property.SetValue(updateObj,originalObj.GetType().GetProperty(property.Name)
         .GetValue(originalObj, null));
      }
   }
   return updateObj;
}
Arkar Moe
  • 51
  • 3