加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net-core – 使用Entity Framework 7处理乐观并发的最佳方法

发布时间:2020-12-15 19:50:45 所属栏目:asp.Net 来源:网络整理
导读:我正在使用ASP.NET 5 rc1和Entity 7 rc1 over coreclr以及示例代码第一次迁移项目. 我正在研究如何管理实体中的并发性,但我找不到有关实体7的推荐并发处理实践的任何好的更新信息. 我有几个实体,他们都实现了接口: public interface IVersionedModel{ byte
我正在使用ASP.NET 5 rc1和Entity 7 rc1 over coreclr以及示例代码第一次迁移项目.

我正在研究如何管理实体中的并发性,但我找不到有关实体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列,我更喜欢使用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();
    }
}

基本上我的问题是,如何使用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
如果我们想要在属性上版本行或ConcurrencyCheck注释,如果我们想要基于属性(而不是整行)的版本,我们似乎可以使用Timestamp注释.

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

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

解决方法

我已经创建了一个静态类来处理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,{scale})");
    }

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读