代码之家  ›  专栏  ›  技术社区  ›  K.Z

实体框架核心引发DBUpdateConcurrencyException

  •  -1
  • K.Z  · 技术社区  · 6 年前

    我正在研究.NET核心实体框架。我有两个班级类型的清单。一个用于更新,另一个用于新条目,添加新记录都工作正常,但这是由上下文实现的。[模型]。添加但更新是由上下文完成的。[模型]。更新引发异常更新我知道没有记录在本地运行时更新。

    $exception  {Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded. 
    

    代码

    List<AnswerDataModel> surveyResponseListToCreate = new 
    List<AnswerDataModel>();
    
        List<AnswerDataModel> surveyResponseListToUpdate = new 
       List<AnswerDataModel>();
    
         if (surveyResponseListToUpdate.Count > 0)
                {
                    foreach (var answerObject in surveyResponseListToUpdate)
                    {
                        Context.Answers.Update(answerObject);
    
                        if (answerObject.AnswerOptions.Count > 0)
                        {
                            foreach (var optItem in answerObject.AnswerOptions)
                            {
                                AnswerOptionDataModel answOpt = new AnswerOptionDataModel();
                                answOpt = optItem;
                                Context.AnswerOptions.Update(answOpt);
                            }
                        }
                    }
                }
    
            var recordsAffected = Context.SaveChanges();
    
                if (!UsingExternalTransaction)
                {
                    FinalizeTransaction(recordsAffected);
                }
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   Steve Py    6 年前

    我无法抗拒引用: “我不认为[你的代码]意味着你认为它意味着什么。”

    假设SurveyResponseListToUpdate是以前加载和修改的实体列表:

    if (answerObject.AnswerOptions.Count > 0) // Unnecessary...
    {
      foreach (var optItem in answerObject.AnswerOptions)
      {
        AnswerOptionDataModel answOpt = new AnswerOptionDataModel(); // does nothing.
        answOpt = optItem; // references existing answer option..
        Context.AnswerOptions.Update(answOpt);
      }
    }
    

    整个过程归结为:

      foreach (var optItem in answerObject.AnswerOptions)
        Context.AnswerOptions.Update(optItem);
    

    你可能遇到的错误是因为 Update 将自动在导航属性中循环,因此当更新父级(应答)时,它的answerOptions也将更新。因此,当您完成尝试保存答案选项的额外步骤时,这些步骤在保存答案时已经更新。如果答案是由您要保存到的同一上下文加载的,那么您应该清楚地看到:

    foreach (var answerObject in surveyResponseListToUpdate)
      Context.Answers.Update(answerObject);
    
    var recordsAffected = Context.SaveChanges();
    

    这应该更新答案及其关联的答案对象。即使添加或删除了选项,更改跟踪也应该完成它的工作,并确保更新所有相关的数据记录。 额外的 if 检查之类的不必要,只是增加了嵌套深度,使代码更难阅读。

    但是,我怀疑您的实际代码与示例所做的有所不同,因为我的测试试图重现您的错误,代码工作良好,甚至在更新父代码后更新子引用。如果上述问题仍然存在,请使用正在运行的代码更新示例。