EF4 Context.ApplyCurrentValues不更新當前值

c#-4.0 entity-framework

我有一個實體,我檢索如下,並與上下文分離:

ctx.Reviews.MergeOption = MergeOption.NoTracking;

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

然後我對關係中的對象進行更改:

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

然後我附加了Object並循環子節點並在需要時更改它的實體狀態。保存更改完成後,不會更新任何內容:

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();

一般承認的答案

因為您從MergeOption.NoTracking開始, MergeOption.NoTracking您的實體是Detached 。然後你修改並附加它們。您應該知道Attach會導致一個Unchanged EntityState - 也就是說,它附加到上下文後它沒有改變。這樣原始值和當前值都具有相同的值集: 修改後的值。這就是為什麼一旦你調用SaveChanges方法它就不會更新。

我想你也誤解了ApplyCurrentValues方法的目的:
它將獲取所提供的分離實體的值,並使用其EntityKey在上下文中定位同一實體。然後它將使用分離實體的屬性值替換附加實體的當前標量值。
在您已經附加分離實體的情況下,您實際上不需要調用它,而是需要將ReviewNote實體的狀態更改為Modified,以便EF對您的數據存儲執行適當的更新方法:

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();


編輯:另一種方法是運行相同的查詢並將ReviewNote對象放入內存,然後在每個對像上調用ApplyCurrentValues,以便只有具有已更改屬性的對象才會進入修改狀態:

// 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();

另請注意, ApplyCurrentValues僅適用於單個實體上的標量屬性 ,並且不會考慮導航屬性,否則我們只需在Review對像上調用它一次,而無需進入循環以將其應用於每個ReviewNote 。



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因