Current values are not updated by EF4 Context.ApplyCurrentValues.

c#-4.0 entity-framework

Question

I have an object that is separate from the context and that I fetch as follows:

ctx.Reviews.MergeOption = MergeOption.NoTracking;

Review review = (from r in ctx.Reviews.Include("ReviewNotes")
                 where r.ReviewID == reviewID
                 select r).First();

I then alter one of the relationship's objects:

if (review.ReviewNotes.Count > 0)
{
  ReviewNote r = review.ReviewNotes.ElementAt(0);
  r.Note = "Ugg " + DateTimeOffset.Now.ToString();
  r.CreatedDate = DateTimeOffset.Now;
}

After that, I loop the object's children and, if necessary, alter the entity state. Nothing changes once you save your modifications.

ctx.Reviews.Attach(review);
foreach (ReviewNote item in review.ReviewNotes)
{
   if (item.ReviewNoteID == 0)
   {
       ctx.ObjectStateManager.ChangeObjectState(item, EntityState.Added);
   }
   else
   {
       key = ctx.CreateEntityKey("ReviewNotes", item);
       if (ctx.TryGetObjectByKey(key, out original))
       {
           ctx.ApplyCurrentValues<ReviewNote>(key.EntitySetName, item);
       }

   }
 }

ctx.ObjectStateManager.ChangeObjectState(review, EntityState.Modified);
ctx.SaveChanges();
1
4
10/28/2010 12:05:41 AM

Accepted Answer

because you begin withMergeOption.NoTracking You are your entitiesDetached . You alter and attach them after that. You should be aware that Attach produces an EntityState of Unchanged, meaning that it has not changed since it was associated to the context. such that the altered ones has the same values as both the initial and current values. As a result, once you run the SaveChanges function, it is not changed.

You may have also misinterpreted the goal ofApplyCurrentValues method:
The detached entity's values will be used, together with its EntityKey, to find the same entity in the context. The property values from the detached entity will then be used to replace the existing scalar values of the associated object.
You don't actually need to contact the detached entity in your situation since you've already connected it; instead, you need to change the state of yourReviewNote In order for EF to run the proper update methods against your data store, you must set entity to Modified:

ctx.Reviews.Attach(review);
foreach (ReviewNote item in review.ReviewNotes) {
   if (item.ReviewNoteID == 0) {
       ctx.ObjectStateManager.ChangeObjectState(item, EntityState.Added);
   }
   else {
       key = ctx.CreateEntityKey("ReviewNotes", item);
       if (ctx.TryGetObjectByKey(key, out original)) {
           // ctx.ApplyCurrentValues(key.EntitySetName, item);
           ctx.ObjectStateManager.ChangeObjectState(item, EntityState.Modified);
       }
   }
 }
ctx.ObjectStateManager.ChangeObjectState(review, EntityState.Modified);
ctx.SaveChanges();


EDIT: A different strategy would be to use the same query to load the ReviewNote objects into memory, then use ApplyCurrentValues on each of them to ensure that only those with updated properties entered the Modified state:

// This time you don't need to attach:
//ctx.Reviews.Attach(review);
// Make sure you have them in the memory:
Review review2 = (from r in ctx.Reviews.Include("ReviewNotes")
                 where r.ReviewID == reviewID
                 select r).First();
foreach (ReviewNote item in review.ReviewNotes) {
   if (item.ReviewNoteID == 0) {
       ctx.ReviewNotes.AddObject(item);
   }
   else {
       key = ctx.CreateEntityKey("ReviewNotes", item);
       if (ctx.TryGetObjectByKey(key, out original)) {
           // Note that the item is a detached object now: 
           ctx.ApplyCurrentValues(key.EntitySetName, item);
       }
   }
 }
ctx.ObjectStateManager.ChangeObjectState(review, EntityState.Modified);
ctx.SaveChanges();

Note that ApplyCurrentValues only functions with scalar attributes on a single entity and does not consider navigation properties; if it did, we could call it once on the Review object rather than needing to enter a loop to apply it to every single ReviewNote.

8
10/28/2010 4:48:51 PM


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