首页 > 解决方案 > 实体框架核心抛出 DbUpdateConcurrencyException

问题描述

我正在研究 .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);
            }

标签: entity-framework.net-core

解决方案


我无法抗拒一句话:“我不认为 [你的代码] 意味着你认为它的意思。”

假设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检查等不是必需的,只是增加了嵌套深度,使代码更难阅读。

但是,我怀疑您的真实代码与示例不同,因为我在测试中尝试重现您的错误,即使在更新父级后更新子级引用,代码也能正常工作。如果上述问题仍然存在,请使用您正在运行的代码更新您的示例。


推荐阅读