【发布时间】:2019-11-07 08:40:01
【问题描述】:
我有一个这样配置的属性:
public byte[] Timestamp { get; set; }
然后在我的 DbContext 中,我像这样使用 Fluent API:
modelBuilder.Entity<MyClass>()
.Property(x => x.Timestamp)
.IsRowVersion()
.IsConcurrencyToken(true);
所以我很自然地继续编写了一个单元测试,以确保时间戳设置错误的实体不会被保存。我使用 Sqlite 和一些自定义 Sql 使 RowVersion 在单元测试中工作,但令我惊讶的是,我从未遇到过异常。然后,我在我们的应用程序中对其进行了测试,当在实体上设置了错误的时间戳时,我也没有收到异常。
var myInstance = await myDbContext.Instances
.Include(x => x...)
.Include(x => x...)
.SingleAsync(x => x.Id == id);
// set other values, add new entities to relationships, aso
myInstance.Timestamp = new byte[] { 1, 2, 3, 4 };
await myDbContext.SaveChangesAsync();
我显然在这里遗漏了一些东西。我认为配置IsRowVersion 足以强制EF Core 在UPDATE 中包含WHERE Timestamp = 子句,但似乎并非如此。如您所见,我也尝试调用IsConcurrencyToken(即使它的默认值为true,只是为了确定)但无济于事。
编辑:我现在已经通过在我的SingleAsync 调用中包含时间戳来“解决”它,但这仍然让我不确定它是否仍然可能不会出现并发异常,因为我的实体上设置了Timestamp保存时显然根本没有检查?
【问题讨论】:
-
您应该删除
.IsConcurrencyToken(true)。似乎它覆盖了IsRowVersion,而后者是what you need。 -
@GertArnold 删除/添加它实际上什么也没做,因为它只会创建一个空迁移。似乎原因是 ef core github.com/aspnet/EntityFrameworkCore/issues/18505 的已知行为
-
那么
.IsRowVersion()显然优先。您应该在数据库中有一个rowversion字段。为了进行测试,您最好在保存更改之前在同一记录上运行原始 SQL 更新语句。这更接近现实。
标签: ef-core-3.0