【问题标题】:EntityFramework SaveChanges() throws concurrent transaction errorEntityFramework SaveChanges() 抛出并发事务错误
【发布时间】:2019-02-21 19:02:56
【问题描述】:

在我的 MVC 应用程序中,我有一个页面从我的 POLICIES 表中加载一条记录,然后在我的视图中使用它。然后,我的视图会在页面上显示来自该记录的数据,但是为了编辑记录数据,用户需要单击“编辑策略”按钮,该按钮会在 EDIT 模式下启动具有相同记录的 jQuery UI 对话框。我意识到我可以让他们从主视图中编辑它,但这不是我的客户想要的。

我遇到的问题是,当我在我的 jQuery UI 对话框中时,当我尝试保存记录时出现以下错误。

FirebirdSql.Data.FirebirdClient.FbException:无等待时发生锁定冲突 交易

我的对话框的 Controller 方法执行以下代码。 PolicyModel 是一个简单的类,用作对话框的 ViewModel,Policy 属性是一个表示 Policy 表的对象。

public ActionResult Policy(int policyNo) {
     PolicyModel policyModel = new PolicyModel();
     policyModel.Policy = dbContext.POLICIES.FirstOrDefault(db => db.POLICY_NO == policyNo);
     return View(policyModel);
}

在“Policy”视图中,我使用以下方法制作标准表单:

@using (Html.BeingForm("SavePolicy", "MyController", FormMethod.Post)) {
    //hidden element for policyNo created with @Html.HiddenFor
    //form elements here created using the @Html.TextBoxFor..etc.
}

要保存的对话框按钮只需使用var formData = new FormData($('#myformid').get(0)); 创建新的 FormData,然后将其传递给我的保存控制器方法。

Save方法设置如下

public ActionResult SavePolicy(PolicyModel policyModel) {

     var policy = dbContext.POLICIES.FirstOrDefault(db => db.POLICY_NO == policyModel.POLICY_NO);

     if (TryUpdateModel(policy,"Policy", updateFields.ToArray())) {
         dbContext.Entry(policy).State = EntityState.Modified;
         dbContext.SaveChanges();
     }

     return Json( new { result = 1, JsonRequestBehavior.AllowGet } );

}

如果我手动将 POLICY_NO 更改为任何其他政策编号,而不是像这样在对话框中当前处于活动状态的编号...

var policy = dbContext.POLICIES.FirstOrDefault(db => db.POLICY_NO == 12345);

存档会正确更新。

这就像对话框视图正在持有资源或其他东西。有什么想法吗?

更新

作为参考,dbContext 的作用域是我的 SavePolicy 方法所在的 Controller 类,如下所示...

public class MainController : Controller {
     private DBModel dbContext = new DBModel();

     // other methods

     public ActionResult SavePolicy(PolicyModel policyModel) {

          // method code as see above

     }

}

【问题讨论】:

  • 考虑在 firebird-net-provider google 群组中提问,您可能会更快得到答案。
  • 这里缺少的是如何管理 dbContext。它是否仅限于请求?
  • @HenkHolterman - 不,它的范围仅限于 SavePolicy 方法所在的 Controller 类。创建使用 MYDB dbContext = new MYDB();
  • @HenkHolterman - 你解决了我的问题。您的问题促使我尝试使用 (MYDB dbContext = new MYDB()) {) 语句将我的数据库对象范围限定为每个方法的本地范围。有效。谢谢!!!!!!!!!!

标签: asp.net-mvc entity-framework model-view-controller firebird firebird2.5


【解决方案1】:

ASP.NET MVC 控制器通常有这样的:

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        db.Dispose();
    }
    base.Dispose(disposing);
}

因此,如果您在操作之外声明上下文,则应验证此方法是否已实现。

事实证明,在第一次执行(选择)时,您的上下文 keeps track of the record at Firebird and it is never disposed。第二次执行将尝试再次选择相同的条目,该条目仍被另一个未正确处理的上下文跟踪。

在每个动作中使用作用域上下文是另一种解决方法,但在我看来它有点麻烦。

【讨论】:

  • 谢谢你。我不知道这种做法,但它看起来很完美。我喜欢这个比到处都使用 () 语句要好得多。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-15
  • 1970-01-01
  • 2022-06-15
  • 1970-01-01
相关资源
最近更新 更多