如果我在我的模型中使用以下字段:
问题是,MySQL不会自动增加这个值。因此,我创建了一个触发器:
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
[Timestamp]
public DateTime RowVersion { get; set; }
然后将该列定义为
`RowVersion` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
我从EF中得到了适当的乐观并发行为。尽管如此,我对使用时间戳并不感到满意,因为它似乎只有秒级分辨率。虽然在1秒内有2个客户端尝试更新相同的记录的机会不大,但这确实可能发生,不是吗?
因此,考虑到这一点,我更喜欢一个简单的整数,每次更新时原子地增加1。这样就不可能错过冲突。我将定义更改为:
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
[Timestamp]
public long RowVersion { get; set; }
问题是,MySQL不会自动增加这个值。因此,我创建了一个触发器:
CREATE TRIGGER update_row_version BEFORE UPDATE on client
FOR EACH ROW
SET NEW.RowVersion = OLD.RowVersion + 1;
现在这一切都能够正常工作了。EF会在必要的时候抛出DbUpdateConcurrencyException异常,且不会因为时间窗口而错过更新。但是,它使用了触发器,我一直在阅读关于它们性能如何糟糕的信息。
那么有更好的方法吗?也许可以覆盖DbContext的SaveChanges()方法,在客户端执行RowVersion增量操作,因此只在数据库上进行单个更新(我假设触发器每次实际上会进行两次更新)?
[Timestamp]public byte[] RowVersion
这个代码能用吗?通常是用于 MSSQL,但不知道 MySQL Provider 是否也能处理它。与 MSSQL 不同,MySQL 没有行版本数据类型。 - TsengWHERE Id=? AND RowVersion=?
。 - TsengCURRENT_TIMESTAMP
的精度为微秒级(6位数字)。我不会过于担心同步更新。 - Gert Arnold