2

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

[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;? 这条线到底是做什么的?为什么需要抛出异常?谢谢

4

1 回答 1

1

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

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

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

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

于 2018-02-09T04:36:39.617 回答