【问题标题】:Best way to handle optimistic concurrency with Entity Framework 7使用 Entity Framework 7 处理乐观并发的最佳方法
【发布时间】:2016-03-02 10:25:10
【问题描述】:

我在 coreclr 上使用 ASP.NET 5 rc1 和 Entity 7 rc1 以及示例代码首次迁移项目。

我正在查看如何在实体中管理并发,但我找不到任何关于实体 7 推荐并发处理实践的良好更新信息。

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

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; }
}

而不是将属性 [Timestamp] 添加到每个 RowVersion 列,我更喜欢使用流畅的配置,因此在我的 DbContext 中,我为每个实体指定我希望将该列作为行版本处理。

但是 Entity 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();
    }
}

基本上我的问题是,如何处理 ASP.NET 5 和 Entity 7 的并发性? 这是我第一次处理这件事,任何建议都将不胜感激。

更新:感谢链接https://stackoverflow.com/users/1922568/joe-audette 提供我找到了一些答案,不幸的是不是全部

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

fluent API 只允许使用.IsConcurrencyToken()配置并发令牌

我还没有找到通过 fluent API 使用专用列对整行进行版本控制的方法(如果 fluent API 允许.IsRowVersion(),那就太好了,但它不允许)

【问题讨论】:

标签: asp.net-core entity-framework-core


【解决方案1】:

我创建了一个静态类来处理 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();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-02
    相关资源
    最近更新 更多