EF4 Context.ApplyCurrentValues ​​не обновляет текущие значения - PullRequest
4 голосов
/ 28 октября 2010

У меня есть сущность, которую я извлекаю следующим образом и отсоединяю от контекста:

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;
}

I затемприсоедините объект и зациклите дочерние элементы и при необходимости измените его состояние объекта.После сохранения изменений ничего не обновляется .:

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 Ответ

8 голосов
/ 28 октября 2010

Поскольку вы начинаете с MergeOption.NoTracking, ваши сущности Detached.Затем вы модифицируете и прикрепляете их.Вы должны знать, что Attach приводит к неизменным EntityState - то есть он не изменился, так как он был присоединен к контексту,Таким образом, исходные и текущие значения имеют одинаковый набор значений: измененные .Вот почему он не обновляется после вызова метода SaveChanges.

Я думаю, что вы также неправильно поняли цель метода ApplyCurrentValues:
Он примет значения предоставленного отдельного объекта и использует его EntityKey, чтобы найти тот же объект в контексте.Затем он заменит текущие скалярные значения присоединенной сущности значениями свойства из отсоединенной сущности.
В вашем случае, когда вы уже прикрепили отсоединенную сущность, вам не нужно вызывать ее, вместо этого вам нужно изменить состояние вашей ReviewNote сущности на Изменено , чтобы 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 ​​длякаждый из них, так что только те, у кого есть измененное свойство, перейдут в состояние Modified :

// 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.

...