我已经按照此处的文档进行操作,并且使用的是SQL Server 2016。(https://ef.readthedocs.io/en/latest/modeling/concurrency.html)
我已经在我的表中添加了一个名为VersionCol的时间戳列,当我运行Scaffold-DbContext时,它会在我的DbContext中的表实体上放置以下属性。
entity.Property(e => e.VersionCol)
.IsRequired()
.HasColumnType("timestamp")
.ValueGeneratedOnAddOrUpdate()
这段代码缺少 .IsConcurrencyToken()
,我已经自己加上了,但在应该出现并发问题的情况下没有抛出任何异常,反而直接覆盖了数据。
是否有什么地方我忽略了?
编辑:
我使用基于数据库的方法(因此没有[Timestamp]或其他注释),并将我的DbContext注入到服务中,在Startup.cs中使用services.AddScoped<IPoRepository,PoRepository>()
进行配置。
它在我的模型中生成一个public byte[] VersionCol { get; set; }
字段,我认为这是正确的。
在我的PoRepository中,我试图使用以下代码更新我的Po:
public void SavePo(PoListing poListing) {
Po po;
try {
po = _context.Po.Where( p => p.Poid == poListing.PoId ).First();
} catch ( ArgumentNullException ) {
throw new ArgumentNullException( "The PO does not exist." );
}
po.AssignedUserId = poListing.AssignedUserId;
po.VersionCol = poListing.VersionCol;
_context.Entry( po ).State = EntityState.Modified;
_context.SaveChanges();
}
PoListing本质上只是Po的一部分,因此它仅具有其某些列(它不是数据库中的表),并且在生成时具有Po的VersionCol。如果PoListing的VersionCol早于它所基于的Po,则应该会产生异常。
编辑2:
这个方法可行,但我无法弄清楚如何使它在不需要创建第二个上下文的情况下工作,并且只使用注入的上下文。
public void SavePo(PoListing poListing) {
DbContextOptionsBuilder<TMS_1000Context> options = new DbContextOptionsBuilder<TMS_1000Context>();
options.UseSqlServer( "Server=DEVSQL16;Database=TMS_1000_Dev;Trusted_Connection=True;MultipleActiveResultSets=true" );
TMS_1000Context context1;
try {
po = _context.Po.Where( p => p.Poid == poListing.PoId ).First();
} catch ( ArgumentNullException ) {
throw new ArgumentNullException( "The PO does not exist." );
}
using ( context1 = new TMS_1000Context( options.Options ) ) {
po.AssignedUserId = poListing.AssignedUserId;
po.VersionCol = poListing.VersionCol;
context1.Update( po );
context1.SaveChanges();
}
}
编辑3:
目前这种方法可行。还有其他方式吗?
public void SavePo(PoListing poListing) {
Po po;
try {
po = _context.Po.Where( p => p.Poid == poListing.PoId ).First();
} catch ( ArgumentNullException ) {
throw new ArgumentNullException( "The PO does not exist." );
}
po.AssignedUserId = poListing.AssignedUserId;
_context.Entry( po ).Property( u => u.VersionCol ).OriginalValue = poListing.VersionCol;
_context.Update( po );
_context.SaveChanges();
}
[Timestamp]
属性还是在DbContext的OnModelCreating
方法中添加,或者你正在尝试从现有数据库脚手架的数据库优先方法?请至少发布你的模型和DbContext代码以及相关的OnModelCreating
。 - Tseng