使用IsConcurrencyToken()设置并发token

  builder.Property(h => h.Owner).IsConcurrencyToken();

使用SQL语句类似以下

  update house set owner = @p0
  where id = 1 and owner = @p1

  -- 通过引用旧的owner值来更新,如果owner值已改变,则更新失败,发出DbUpdateConcurrencyException。

捕获DbUpdateConcurrencyException,获取新Token的值。

  catch (DbUpdateConcurrencyException ex)
  {
      var entry = ex.Entries.First();
      var dbValues = await entry.GetDatabaseValuesAsync();
      string newOwner = dbValues.GetValue<string>(nameOf(House.Owner));
      Console.WriteLine($"concurrency error, {newOwner} is owner now");
  }

使用RowVersion控制并发

  1. 增加RowVer属性
  public byte[] RowVer { get; set; }
  1. 设置RowVersion
  builder.Property(c => c.RowVer).IsRowVersion();

原理和上面一样,只是改为判断RowVersion。
3. 测试代码和上例一样,也通过捕获DbUpdateConcurrencyException,取得owner的新值。

注意

方案1,会有ABA的问题,即值发生过改变,但又改回来了,这样就需要考虑RowVersion是不是更合适了。