我应该期待什么持续性的行为,当在这种情况下
我的代码与几个嵌套循环大块这需要在数据库中更新最终多条记录。我想尽量减少实体框架的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的选项)?
我不认为你不必担心。一旦你在你的物体上拨打Attach
,你是否保留自己的引用并不重要;它应该没问题。
需要记住的是,您的物体的寿命长达,某人。所以,按理说,调用Attach
会导致你的DbSet
引用您的对象,它甚至还活着后,您不引用它了自己从而保持。
然而,做的最好的事情,在我看来,就是只要给它一个尝试,看看会发生什么!
是的,这是按照您在各种情况下所建议的方式工作的,并且更好的是,上下文会自动追踪并执行对象之间关系的修复。因此,在并发不是主要问题的情况下,尽可能晚地调用Save()似乎是非常可行的。非常感谢您的帮助! – Shane 2012-07-12 20:00:19
好吧,事实证明,是的,有一个参考,但不是副本。因此,在我上面的示例中,由于每次通过循环都将obj赋值给一个新对象,因此一切都很好。但是,不能做的是重复使用同一个对象,将它传递给Attach(),并期望存储库中有实例。对于有经验的EF开发人员来说也许是显而易见的,但不一定直观来自旧的“commit to db”世界。我曾预料它的行为有点像db的内存缓存表示,但事实并非如此。 – Shane 2012-07-13 15:37:46
所以,你写的所有代码,但你想知道它是否会奏效。你有没有考虑过只是执行它并发现? – Servy 2012-07-11 19:56:27
你在问这个问题:“这个特定的代码段是否工作?”最好通过运行来解决。它只调用一次更新,所以你不会想出任何更少的东西。这个问题是:“这个工作法典是不是很好的做法,还是它可以提高效率?”是代码审查的问题。 – Servy 2012-07-11 20:37:41