我应该期待什么持续性的行为,当在这种情况下

问题描述:

我的代码与几个嵌套循环大块这需要在数据库中更新最终多条记录。我想尽量减少实体框架的SaveChanges()调用次数。另请注意,我们正在使用存储库模式。我应该期待什么持续性的行为,当在这种情况下

基本上我迭代的集合,需要更新两个集合中,并在每次迭代中,从数据库中检索和语境通过从集合中项的另一对象的项目。

示例代码:

foreach (var outer in outerList) 
      { 
       obj = unit.GetRepository<MyObj>().Get(s => 
        s.id = myId 
        ).SingleOrDefault(); 

       obj.value += outer.value;      
       outer.objId = obj.objId; 

       unit.GetRepository<MyOuterObj>().Update(outerObj); 
       unit.GetRepository<MyObj>().Update(obj);      
      } 
      unit.Save(); 

来更新(调用)执行以下操作:

public virtual void Update(T entityToUpdate) 
    { 
     if(entityToUpdate is AuditModelBase) 
     { 
      var model = entityToUpdate as AuditModelBase; 
      model.UpdatedAt = DateTime.UtcNow; 
     } 

     DbSet.Attach(entityToUpdate); 
     Context.Entry(entityToUpdate).State = EntityState.Modified; 
    } 

而且调用保存()当然下面执行:

_context.SaveChanges(); 

所以我的问题是,因为我每次通过循环将obj重新赋值为不同的值,我是否需要Save() foreach循环以便所有“obj”实例持续存在。或者DbSet.Attach(obj)确保每个单独的实例都被更新,无论我在循环中如何处理对象。

也许更好的方式来问这个是:

鉴于它看起来像装()是传址引用,以便因此只有我最后OBJ将被更新,有什么用EF最佳实践完成这种事情(不包括直接调用SQL的选项)?

+0

所以,你写的所有代码,但你想知道它是否会奏效。你有没有考虑过只是执行它并发现? – Servy 2012-07-11 19:56:27

+0

你在问这个问题:“这个特定的代码段是否工作?”最好通过运行来解决。它只调用一次更新,所以你不会想出任何更少的东西。这个问题是:“这个工作法典是不是很好的做法,还是它可以提高效率?”是代码审查的问题。 – Servy 2012-07-11 20:37:41

我不认为你不必担心。一旦你在你的物体上拨打Attach,你是否保留自己的引用并不重要;它应该没问题。

需要记住的是,您的物体的寿命长达,某人。所以,按理说,调用Attach会导致你的DbSet引用您的对象,它甚至还活着后,您不引用它了自己从而保持。

然而,做的最好的事情,在我看来,就是只要给它一个尝试,看看会发生什么!

+0

是的,这是按照您在各种情况下所建议的方式工作的,并且更好的是,上下文会自动追踪并执行对象之间关系的修复。因此,在并发不是主要问题的情况下,尽可能晚地调用Save()似乎是非常可行的。非常感谢您的帮助! – Shane 2012-07-12 20:00:19

+0

好吧,事实证明,是的,有一个参考,但不是副本。因此,在我上面的示例中,由于每次通过循环都将obj赋值给一个新对象,因此一切都很好。但是,不能做的是重复使用同一个对象,将它传递给Attach(),并期望存储库中有实例。对于有经验的EF开发人员来说也许是显而易见的,但不一定直观来自旧的“commit to db”世界。我曾预料它的行为有点像db的内存缓存表示,但事实并非如此。 – Shane 2012-07-13 15:37:46