EF4 Context.ApplyCurrentValues不更新当前值 [英] EF4 Context.ApplyCurrentValues does not update current values

查看:197
本文介绍了EF4 Context.ApplyCurrentValues不更新当前值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个实体,我如下检索,并从上下文中分离:

  ctx.Reviews.MergeOption = MergeOption无跟踪; 

查看评论=(从r在ctx.Reviews.Include(ReviewNotes)
其中r.ReviewID == reviewID
选择r).First();

然后我对关系中的对象进行更改:

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

然后我添加对象并循环孩子,并更改它的实体状态中。当保存更改时,不会更新任何内容。

  ctx.Reviews.Attach 
foreach(ReviewNote item in review.ReviewNotes)
{
if(item.ReviewNoteID == 0)
{
ctx.ObjectStateManager.ChangeObjectState(item,EntityState。添加);
}
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();因为你从开始
$ <$> $ b

解决方案.NoTracking 您的实体已分离。然后您修改和附加它们。您应该知道, 附加 会导致 未变更 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();



EDIT:
方法是运行相同的查询并将ReviewNote对象获取到内存中,然后在每个对象上调用ApplyCurrentValues,以使只有具有更改属性的对象进入修改状态:

  //这次你不需要附加:
//ctx.Reviews.Attach(review);
//确保你在内存中有它们:
查看review2 =(来自r在ctx.Reviews.Include(ReviewNotes)
其中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)){
//注意,该项目现在是一个分离的对象:
ctx.ApplyCurrentValues(key.EntitySetName,item);
}
}
}
ctx.ObjectStateManager.ChangeObjectState(review,EntityState.Modified);
ctx.SaveChanges();

另请注意,ApplyCurrentValues 只适用于标量属性在单个实体上,并且不会考虑导航属性,否则我们只会在Review对象上调用一次,而不必进入循环以将其应用于每个ReviewNote。


I have a entity that I retrieve as follows and is detached from the context:

ctx.Reviews.MergeOption = MergeOption.NoTracking;

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

I then make changes to an object in the relationship:

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

I then attach the Object and loop the children and change it's entity state if needed. When save changes is done nothing is updated.:

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

解决方案

Because you start with MergeOption.NoTracking your entities are Detached. Then you modify and attached them. You should be aware that Attach results in an Unchanged EntityState — that is, it has not changed since it was attached to the context. So that both the original and current values have the same set of values: the modified ones. That's why it does not get updated once you call SaveChanges method.

I think you also misunderstood the purpose of ApplyCurrentValues method:
It will take the values of the provided detached entity and use its EntityKey to locate the same entity in the context. Then it will replace the attached entity’s current scalar values with the property values from the detached entity.
In your case where you already attached the detached entity, you don't really need to call it, instead you need to Change the state of your ReviewNote entity to Modified so that EF will execute appropiate update methods against your data store:

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: Another approach would be to run the same query and get the ReviewNote objects into the memory and then call ApplyCurrentValues on each of them so that only the ones that has a changed property would go into 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();

Also note that ApplyCurrentValues does only work with the scalar properties on a single entity and would not take navigation properties into account, otherwise we would just call it one time on Review object without having to go into a loop to apply it on each and every ReviewNote.

这篇关于EF4 Context.ApplyCurrentValues不更新当前值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆