使用Entity Framework 7处理乐观并发的最佳方法

ibe*_*dev 5 entity-framework-core asp.net-core

我正在使用ASP.NET 5 rc1和Entity 7 rc1 over coreclr以及示例代码第一次迁移项目.

我正在研究如何管理实体中的并发性,但我找不到有关实体7的推荐并发处理实践的任何好的更新信息.

我有几个实体,他们都实现了接口:

public interface IVersionedModel
{
    byte [] RowVersion { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

例如:

public class User : IVersionedModel
{
    public Guid UserId { get; set; }
    public string Name { get; set; }
    public byte[] RowVersion { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

而是将属性添加[Timestamp]到每个RowVersion列,我更喜欢使用fluent配置,因此在我的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();
    }
}
Run Code Online (Sandbox Code Playgroud)

基本上我的问题是,如何使用ASP.NET 5和Entity 7处理并发?这是我第一次处理这件事,任何建议都会受到赞赏.

更新:感谢链接/sf/users/134579791/提供了我找到了一些答案,不幸的是并非全部

根据http://docs.efproject.net/en/latest/modeling/concurrency.html#how-concurrency-tokens-work-in-ef ,Timestamp如果我们想在一个版本上修改行或ConcurrencyCheck注释,我们似乎可以使用注释.属性,如果我们想要基于属性(而不是整行)的版本.

流畅的API仅允许使用配置并发令牌 .IsConcurrencyToken()

我还没有找到一种方法通过流畅的API来使用专用列对整行进行版本化(如果流畅的API允许.IsRowVersion(),它会很好,但它不会)

And*_*net 3

我创建了一个静态类来处理 EF7 ModelBuilder 的此功能和其他缺失的功能(谨慎使用,未在生产环境中进行测试)

public static class SqlServerModelBuilderExtensions
{
    public static PropertyBuilder<decimal?> HasPrecision(this PropertyBuilder<decimal?> builder, int precision, int scale)
    {
        return builder.HasColumnType($"decimal({precision},{scale})");
    }

    public static PropertyBuilder<decimal> HasPrecision(this PropertyBuilder<decimal> builder, int precision, int scale)
    {
        return builder.HasColumnType($"decimal({precision},{scale})");
    }

    public static PropertyBuilder<byte[]> IsRowVersion(this PropertyBuilder<byte[]> builder)
    {
        return builder.HasColumnType("rowversion").IsConcurrencyToken().ValueGeneratedOnAdd();
    }
}
Run Code Online (Sandbox Code Playgroud)