Asp.net core 使用Entity Framework 7处理乐观并发的最佳方法
我在coreclr上使用ASP.NET 5 rc1和Entity 7 rc1,并使用一个示例代码优先迁移项目 我正在研究如何管理实体中的并发性,但是我找不到任何关于实体7的推荐并发处理实践的更新信息 我有几个实体,它们都实现了接口:Asp.net core 使用Entity Framework 7处理乐观并发的最佳方法,asp.net-core,entity-framework-core,Asp.net Core,Entity Framework Core,我在coreclr上使用ASP.NET 5 rc1和Entity 7 rc1,并使用一个示例代码优先迁移项目 我正在研究如何管理实体中的并发性,但是我找不到任何关于实体7的推荐并发处理实践的更新信息 我有几个实体,它们都实现了接口: public interface IVersionedModel { byte [] RowVersion { get; set; } } 例如: public class User : IVersionedModel { public Guid
public interface IVersionedModel
{
byte [] RowVersion { get; set; }
}
例如:
public class User : IVersionedModel
{
public Guid UserId { get; set; }
public string Name { get; set; }
public byte[] RowVersion { get; set; }
}
我更喜欢使用fluent配置,而不是向每个RowVersion列添加属性[Timestamp]
,因此在我的DbContext中,我为每个实体指定希望将该列作为行版本处理的属性
但是,实体7似乎不再支持选项.IsRowVersion()
但是它有选项IsConcurrencyToken()
,这应该足够了,但是在代码优先迁移中,它会生成一个可为空的varbinary列,并且在插入/更新行时不会自动递增
我想知道最好的办法是在数据库中更新或插入实体时通过增加版本来显式管理每行的版本。。
这是我的DbContext
public class AppDbContext : DbContext
{
public AppDbContext() : base()
{
}
public DbSet<User> Users { get; set; }
public DbSet<Organization> Organizations { get; set; }
public DbSet<Membership> Memberships { get; set; }
public override int SaveChanges()
{
//increase entity version for concurrency purposes
foreach(var dbEntityEntry in ChangeTracker.Entries()
.Where(x => x.State == EntityState.Added || x.State == EntityState.Modified))
{
IVersionedModel entity = dbEntityEntry.Entity as IVersionedModel;
if(entity != null)
{
//Increase byte[] RowVersion?
}
}
return base.SaveChanges();
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().Property(u => u.RowVersion).IsConcurrencyToken();
modelBuilder.Entity<Organization>().Property(o => o.RowVersion).IsConcurrencyToken();
modelBuilder.Entity<Membership>().Property(m => m.RowVersion).IsConcurrencyToken();
}
}
公共类AppDbContext:DbContext
{
公共AppDbContext():base()
{
}
公共数据库集用户{get;set;}
公共数据库集组织{get;set;}
公共数据库集成员身份{get;set;}
公共覆盖int SaveChanges()
{
//为并发目的增加实体版本
foreach(ChangeTracker.Entries()中的var dbEntityEntry)
.Where(x=>x.State==EntityState.Added | | x.State==EntityState.Modified))
{
IVersionedModel实体=dbEntityEntry。实体为IVersionedModel;
如果(实体!=null)
{
//增加字节[]行版本?
}
}
返回base.SaveChanges();
}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
modelBuilder.Entity().Property(u=>u.RowVersion).IsConcurrencyToken();
modelBuilder.Entity().Property(o=>o.RowVersion.IsConcurrencyToken();
modelBuilder.Entity().Property(m=>m.RowVersion).IsConcurrencyToken();
}
}
基本上我的问题是,如何处理ASP.NET 5和Entity 7的并发性?
这是我第一次处理这件事,任何建议都将不胜感激
更新:感谢提供的链接,我找到了一些答案,不幸的是,并不是全部
依照
如果我们想对一行进行版本设置,似乎可以使用Timestamp
注释;如果我们想根据一个属性(而不是整行)进行版本设置,则可以对属性使用ConcurrencyCheck
注释
fluent API仅允许使用.IsConcurrencyToken()
我还没有找到通过fluent API使用专用列对整行进行版本设置的方法(如果fluent API允许使用
.IsRowVersion()
,那就好了,但它不允许)我创建了一个静态类来处理EF7 ModelBuilder的这一特性和其他缺失的特性(谨慎使用,未在生产环境中测试)
公共静态类SqlServerModelBuilderExtensions
{
公共静态PropertyBuilder HasPrecision(此PropertyBuilder生成器,int-precision,int-scale)
{
返回builder.HasColumnType($“decimal({precision},{scale})”);
}
公共静态PropertyBuilder HasPrecision(此PropertyBuilder生成器,int-precision,int-scale)
{
返回builder.HasColumnType($“decimal({precision},{scale})”);
}
公共静态PropertyBuilder IsRowVersion(此PropertyBuilder生成器)
{
返回builder.HasColumnType(“rowversion”).IsConcurrencyToken().ValueGeneratedAnd();
}
}
主题是否可以更改为“乐观并发”而不是“并发”,因为它具有误导性?主题是否可以更改为乐观并发。您在此处看到关于并发令牌的文档了吗?