IsConcurrencyToken(true) 实际上不检查并发令牌
IsConcurrencyToken(true) does not actually check concurrency tokens
我有一个 属性 配置如下:
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
,只是为了确定)但无济于事。
编辑:我现在已经 "around" 通过在我的 SingleAsync
调用中包含时间戳来工作,但这仍然让我不确定它是否仍然有可能得不到并发异常,因为 Timestamp
保存时显然根本没有检查我实体上的设置?
这是 EF 核心的已知行为,如此处记录:
https://github.com/aspnet/EntityFrameworkCore/issues/18505
手动更改令牌的值被视为空操作,因为从数据库查询的原始值正用于并发检查。手动更改该值没有任何作用,因为它实际上被忽略了。
如果数据库有较新版本的实体, 可以手动设置令牌的值并使 EF Core 的乐观并发检查失败:
db.Entry(entity).Property(nameof(Entity.ConcurrencyToken)).OriginalValue = entity.ConcurrencyToken;
根据this comment in
我有一个 属性 配置如下:
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
,只是为了确定)但无济于事。
编辑:我现在已经 "around" 通过在我的 SingleAsync
调用中包含时间戳来工作,但这仍然让我不确定它是否仍然有可能得不到并发异常,因为 Timestamp
保存时显然根本没有检查我实体上的设置?
这是 EF 核心的已知行为,如此处记录:
https://github.com/aspnet/EntityFrameworkCore/issues/18505
手动更改令牌的值被视为空操作,因为从数据库查询的原始值正用于并发检查。手动更改该值没有任何作用,因为它实际上被忽略了。
如果数据库有较新版本的实体, 可以手动设置令牌的值并使 EF Core 的乐观并发检查失败:
db.Entry(entity).Property(nameof(Entity.ConcurrencyToken)).OriginalValue = entity.ConcurrencyToken;
根据this comment in