EntityFramework SaveChanges()引发并发事务错误

时间:2019-02-21 19:02:56

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

在我的MVC应用程序中,我有一个页面,该页面从POLICIES表中加载记录,然后在View中使用它。然后,“我的视图”会将来自该记录的数据显示在页面上,但是,要编辑记录数据,用户需要单击“编辑策略”按钮,这将在编辑模式下启动具有相同记录的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);
}

在“政策”视图中,我使用以下方法创建标准表单:

@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);

保存将正确更新。

就像对话框View正在保留资源或其他东西一样。有什么想法吗?

更新

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

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

     // other methods

     public ActionResult SavePolicy(PolicyModel policyModel) {

          // method code as see above

     }

}

1 个答案:

答案 0 :(得分:2)

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。第二次执行将尝试再次选择相同的条目,但未被正确处理的另一个上下文仍会跟踪该条目。

在每个动作中使用范围内的上下文是另一种解决方法,但从我的角度来看,这有点麻烦。