DbEntityEntry OriginalValues与TryUpdateModel RowVersion以避免并发更新(乐观)

时间:2017-09-19 07:50:21

标签: c# asp.net-mvc rowversion

我正在从一本书中使用C#中的EF进行ASP.NET MVC项目,这部分是为了避免从不同的会话同时更新实体。 这本书很棒但不幸的是在这一部分解释是不够的,如果有人能帮我理解,我将不胜感激。 我会尝试省略不相关的代码。该模型基本上只有一个属性“Name”,所以它非常简单:

[HttpPost]
public ActionResult Edit(int? id, byte[] rowVersion)
{
    string[] fieldsToBind = new string[] { "Name", "RowVersion" };
    var categoryToUpdate = db.Categories.Find(id);
    if (TryUpdateModel(categoryToUpdate, fieldsToBind))
        {
            try
            {
                db.Entry(categoryToUpdate).OriginalValues["RowVersion"] = 
                   rowVersion;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            catch (DbUpdateConcurrencyException ex)
            {//... and the code goes on to handle the concurrent update 
             //    scenario
            }

这是我不明白的: 如果TryUpdateModel方法成功更新了模型,并绑定了新值“Name”和“RowVersion”(由视图提供),为什么我必须包含以下行:db.Entry(categoryToUpdate).OriginalValues [“RowVersion” ] = rowVersion;?这条线究竟做了什么?为什么抛出异常需要它? 感谢

1 个答案:

答案 0 :(得分:0)

这与EF内部工作方式有关。为此语句生成UPDATE命令时,EF将查找OriginalValues中存在RowVersion值的行。

需要添加该行,因为实体是使用以下行从DB加载的: db.Categories.Find(id);

因为实体的最新值是使用此行从DB加载的,所以除非您更改存储在OriginalValues中的RowVersion值,否则不会出现并发异常。

如果未从DB加载实体并且通过将其附加到上下文来执行更新,那么就不需要在OriginalValues中设置RowVersion。