Wednesday, 27 October 2010

How to Make LINQ to SQL Check for Changes After Attach (or AttachAll)

dbContext.Entity.Attach(entity, true);
//submit insert or update to db
dbContext.SubmitChanges();

Problem: entity was saved, but its dependencies weren't.

Solution 1: Try to loop its dependencies and attach manually
    foreach (var child in entity.children)
   {
          dbContext.Child.Attach(child);
   
          get error at this line: An entity can only be attached as modified without original state if it declares a version member or does not have an update check policy.
   }

- Solution 1 is completely wrong to resolve the problem
Root cause of Problem: LINQ to SQL assumes that the object you are attaching is un-modified. True, there is an overloaded method "AttachAll(items, true)" that forces LINQ to view those objects as 'modified', but that method only works if your table has a TimeStamp field.

How to resolve: So, how do I tell LINQ to SQL to see if there have been changes made to already-existing entities? By using the "Refresh" method:
// Add this line before "SubmitChanges"
dataContext.Refresh(RefreshMode.KeepCurrentValues, entity);

Completed code as following
.Entity.Attach(entity, true);
dbContext.Child.InsertAllOnSubmit(entity.Children.Where(r => r.Id == 0));

dbContext.Refresh(RefreshMode.KeepCurrentValues, entity);
dbContext.Refresh(RefreshMode.KeepCurrentValues, entity.Children.Where(r => r.Id != 0));


//submit insert or update to db
dbContext.SubmitChanges();

No comments: