我的项目针对 SQL Server 2012 使用 EF(使用自跟踪模板测试版本 4,使用默认模板测试版本 5,所有数据库优先)。数据库表中的每个表都定义了一个 rowversion
( timestamp
) 列。
在它的核心中使用 EF,这意味着我的数据库更新代码看起来像这样:
using (var db = new MyContext())
{
//db.Entry(myInstance).State = EntityState.Modified;
db.SaveChanges();
}
不会触发任何
rowversion
警报。我运行并行客户端,每个客户端读取相同的记录,对其进行更改,然后每个将其写入数据库。接受所有更新,不应用并发。我是否必须为我的更新命令使用存储过程(使用一个声明我的
rowversion
值的 where 子句)让 EF 确认“内置”并发,或者是否有另一种方式(配置、特定方法调用)来制作我的代码工作? 最佳答案
这是答案(我已经给了它几个星期的 POC):RowVersion
中的
TimeStamp
(或 SQL
字段类型)与任何其他字段一样是一个字段(除了是强制性的和自增的)。在更新时有一个特定的数据库处理它的值(即增加它),但没有特定的数据库处理在更新之前比较它的值。 EF
在另一边允许您为每个字段定义 ConcurrencyMode
( edmx
)。如果需要,您可以用 ConcurrencyMode=Fix
(而不是默认的 None
)标记所有字段,从而将所有字段都包含在更新的 where 子句中(将实体的原始值与数据库中记录的当前值进行比较)。但是,使用该模式为每个实体设置一个字段更容易,即 RowVersion
字段。特别是因为唯一为您维护它的一方是数据库。 System.Data.OptimisticConcurrencyException
隔离错误。您仍然必须远离操作对象集的 EF
工作流,例如使用 myObjectSet.Attach(myEntity)
,它会访问数据库以获取当前数据并将您的更改合并到其中。由于 RowVersion
字段通常是不变的,更新会以数据库的当前值触发,不会导致并发异常。 关于 Entity Framework 支持 SQL rowversion,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22193961/