C# 在这种情况下,我应该期望什么样的持久性行为

C# 在这种情况下,我应该期望什么样的持久性行为,c#,entity-framework,repository-pattern,C#,Entity Framework,Repository Pattern,我有一大块代码,其中包含几个嵌套循环,最终需要更新数据库中的许多记录。我正在尽量减少对Entity Framework的SaveChanges()调用的数量。还要注意,我们使用的是存储库模式 本质上,我正在迭代一个集合,需要更新集合中的项,并且在每次迭代时,更新从db检索的另一个对象,并由集合中的项上下文化 示例代码: foreach (var outer in outerList) { obj = unit.GetRepository&l

我有一大块代码,其中包含几个嵌套循环,最终需要更新数据库中的许多记录。我正在尽量减少对Entity Framework的SaveChanges()调用的数量。还要注意,我们使用的是存储库模式

本质上,我正在迭代一个集合,需要更新集合中的项,并且在每次迭代时,更新从db检索的另一个对象,并由集合中的项上下文化

示例代码:

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();
当然,对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重新指定给不同的值时,我是否需要在foreach循环中使用Save(),以便所有“obj”实例都能持久存在。或者DbSet.Attach(obj)是否确保无论我如何处理循环中的对象,都会更新每个实例

或者更好的提问方式是:


考虑到Attach()看起来像是通过引用传递的,因此只有我的最后一个obj会被更新,EF实现这类事情的最佳实践是什么(不包括直接调用SQL的选项)?

我认为您不必担心。在对象上调用
Attach
后,无论您是否保留对该对象的引用;应该没问题

要记住的是,你的对象只要有人引用它,它就会存在。因此,调用
Attach
会导致
DbSet
引用您的对象,从而即使您自己不再引用它,也能使它保持活动状态


然而,在我看来,最好的办法就是尝试一下,看看会发生什么

所以你写了所有的代码,但是你想知道它是否能工作。你是否曾经考虑过执行它并找出答案?你问的问题是:“这个特定的代码片段是否工作?”这是通过运行它最好的回答。它只调用一次更新,所以你不会想出任何效果更低的方法。“这是有效的代码实践,还是可以提高效率?”这是一个代码审查的问题。是的,这在各种场景中都是有效的,更好的是,上下文自动跟踪并修复对象之间的关系。因此,在并发性不是主要问题的场景中,尽可能晚地调用Save()似乎是非常可行的。非常感谢你的回答!好吧,事实证明,是的,有一份参考文献,但没有一份副本。因此,在上面的示例中,由于每次通过循环时我都将obj指定给一个新对象,所以一切都很好。但是,不能重复使用同一对象,将其传递给Attach(),并期望存储库中有实例。对于经验丰富的EF开发人员来说,这可能是显而易见的,但不一定是来自旧的“commit to db”世界的直觉。我原以为它的行为有点像db的内存缓存表示,但事实并非如此。