Search code examples
silverlight-4.0entity-framework-4wcf-ria-services

WCF RIA Services SP1, Entity Framework 4, updating only changed columns


I use LinqToEntitiesDomainService class to update database with Silverlight 4 client. There's AttachAsModified extended method for entity framework ObjectContext which allows you supply original entity property values:

Order original = this.ChangeSet.GetOriginal(currentOrder);
this.ObjectContext.Orders.AttachAsModified(currentOrder, original);

By default, WCF RIA Services doesn't send original values to the server, so one needs to apply [RoundtripOriginal()] attribute to his/her entity.

However, even if I supply original values, SQL generated by Entity framework updates all columns, not only changed ones. Since AttachAsModified() method isn't native ObjectContext class method (it's extended method defined in ObjectContextExtensions class), I tried to use ApplyOriginalValues method which is defined in ObjectSet class. No change. It seems entity framework 4.1, which was released recently may have solution (not sure). How about entity framework 4? Is it possible EF to generate sql to update only changed columns?


Solution

  • I did ask similar question on MSDN forums, and it is confirmed that WCF RIA Services will change all columns. Alternative is,

    You can fetch a copy from database, compare and mark SetModifiedProperty manually by using reflection.

    // change state of entity as Unmodified/Unchanged...
    original.EntityState = Unchanged;
    
    // this is copy form database...
    // Use different context
    MyOrderContext context = new MyOrderContext();
    Order dbOriginal = context.Orders.First( x=>x.OrderID == original.OrderID);
    
    foreach(PropertyInfo p in copy.GetTypes().GetProperties()){
       Object originalValue = p.GetValue(dbOriginal);
       Object newValue = p.GetValue(original);
       if(originalValue!=null && newValue!=null 
           && originalValue.Equals(newValue)){
           continue;
       }
       // resetting this will 
       // make entity's only current
       // property as changed
       p.SetValue(original,originalValue);
       p.SetValue(original,newValue);
    }
    

    You may have to change code as per situation, check if property is readonly or not and this is just a sample but it will help you to build upon it.