实体框架对SQL行版本的支持

use*_*082 4 sql entity-framework rowversion

我的项目针对SQL Server 2012使用EF(使用自跟踪模板的EF版本进行了测试,使用默认模板的版本5进行了测试,所有数据库优先)均使用SQL进行测试。数据库表定义了每个rowversiontimestamp)列。

在其核心中使用EF,这意味着我的数据库更新代码看起来像这样:

using (var db = new MyContext())
{
  //db.Entry(myInstance).State = EntityState.Modified;
  db.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)

不会触发任何rowversion警报。我运行并行客户端,每个客户端读取同一条记录,对其进行更改,然后将其写入数据库。接受所有更新,不应用并发。

我是否需要为我的更新命令(使用一个声明我的rowversion值的where子句)使用存储过程,以使EF确认“内置”并发性,或者还有另一种方式(配置,特定方法调用)来使我的代码正常工作?

use*_*082 6

答案是这样的(我已经给POC几个星期了):

  1. RowVersion(或TimeStamp栏位类型)中的(与栏位类型相同)SQL是其他栏位(强制性和自我递增除外)。数据库在更新时会对其值进行特定的处理(即递增),但是在更新前没有比较其值的特定数据库处理。
  2. EF另一方面,您可以ConcurrencyMode为每个字段(edmx)定义。如果需要,可以用ConcurrencyMode=Fix(而不是默认值None)标记所有字段,从而将所有字段都包含在更新的where子句中(将实体的原始值与数据库中记录的当前值进行比较)。但是RowVersion,使用该模式为每个实体设置一个字段(即字段)会更容易。特别是因为数据库的唯一维护者是您。
  3. 完成此操作后,您一定会遇到System.Data.OptimisticConcurrencyException隔离错误。您仍然必须远离EF操纵对象集的工作流,例如使用myObjectSet.Attach(myEntity),它会访问数据库以获取当前数据并将更改合并到其中。由于该RowVersion字段通常保持不变,因此更新将使用数据库中的当前值触发,并且不会导致并发异常。