zoukankan      html  css  js  c++  java
  • Entity Framework 6 Code First 系列:无需修改实体和配置-在MySql中使用和SqlServer一致的并发控制

    无需修改实体和配置,在MySql中使用和SqlServer一致的并发控制。修改RowVersion类型不可取,修改为Timestamp更不可行。Sql Server的RowVersion生成一串唯一的二进制保证Row的版本,无关TimeStamp,更无论TimeStamp的精度问题。使用MySql触发器只能解决uuid的插入的默认值和更新的随机值,由于MySql的自身为了防止无限递归的策略,它的触发器无法在当前表的触发器中更新当前表,所以触发器无法实现更新在SqlServer中由数据库生成的RowVersion字段的值。所以MySql中的RowVersion只能由应用程序赋值。

    在EF中采用IsConcurrencyToken配置后RowVersion即自动用于where子句中用于比较Row Version,通过重写SaveChanges方法在每次添加和更新时设置RowVersion的值即可实现在更新时同时比较Row Version的当前版本和更新Row Version的目的,同时可以正确的取回更新后的Row Version值。

    1.定义并发控制字段

      public interface IRowVersion
          {
              byte[] RowVersion { get; set; }
          }

    2.配置并发控制字段

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
                modelBuilder.Configurations.AddFromAssembly(typeof(MySqlDbContext).Assembly);
                modelBuilder.Properties().Where(o => typeof(IRowVersion).IsAssignableFrom(o.DeclaringType)&&o.PropertyType==typeof(byte[])&&o.Name=="RowVersion")
                    .Configure(o => o.IsConcurrencyToken().HasDatabaseGeneratedOption(DatabaseGeneratedOption.None));
                Database.SetInitializer(new MySqlDbInitializer());
            }

    3.手动对RowVersion赋值

        public override int SaveChanges()
    {
      this.ChangeTracker.DetectChanges();
      var objectContext = ((IObjectContextAdapter)this).ObjectContext;
      foreach (ObjectStateEntry entry in objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Modified | EntityState.Added))
      {
        var v = entry.Entity as IRowVersion;
        if (v != null)
        {
          v.RowVersion = System.Text.Encoding.UTF8.GetBytes(Guid.NewGuid().ToString());
        }
      }
      return base.SaveChanges();
    }
    

    4.检查生成的Sql语句

    UPDATE `Customer` SET `PhoneNumber`=@gp1, `RowVersion`=@gp2 WHERE (`Id` = 1) AND (`RowVersion` = @gp3)
    
    
    -- @gp1: '635655975120384389' (Type = String, IsNullable = false, Size = 18)
    
    -- @gp2: 'System.Byte[]' (Type = Object, IsNullable = false, Size = 36)
    
    -- @gp3: 'System.Byte[]' (Type = Object, IsNullable = false, Size = 36)

    5.查看数据中的RowVersion

    6.准备测试代码

        public static void Test()
    {
      var db1 = GetContext();
      var customer1 = db1.Set<Customer>().FirstOrDefault();
      customer1.PhoneNumber="t1";
      using (var db2 = GetContext())
      {
        var customer2 = db2.Set<Customer>().FirstOrDefault();
        customer2.PhoneNumber = "t2";
        db2.SaveChanges();
      }
      db1.SaveChanges();
    }
    

    7.查看测试结果:

    总结:

    1.需要唯一版本号的生成支持,Sql Server(Compact)本身支持,MySql的uuid函数也支持。

    2.需要设置Insert时的RowVersion默认值和更新RowVersion版本号,Sql Server(Compact)本身支持,MySql只支持不能用于RowVersion的TimeStamp的默认值和自动更新。因此在MySql中只能在应用中设置Row Version。

    不存在的缺点:

    1.ASP.NET慢(没设置好IIS的Application Initialization和回收配置等选项)

    2.Entity Framework慢(没有设置per request one DbContext和Generate Views)

    3.Entity Framework加载数据太多(不正确使用AutoMapper和延迟加载)

    4.Entity Framework不需要IRepository(IRepository的价值在测试和隔离实现)

  • 相关阅读:
    杨老师课堂_VBA学习教程之根据部门列创建工作表
    杨老师课堂_Java核心技术下之控制台模拟微博用户注册案例
    杨老师课堂_Java核心技术下之控制台模拟记事本案例
    杨校老师课堂之JavaScript右下角广告弹框教程
    JavaScript的数组知识案例之随机点名器
    SET QUOTED_IDENTIFIER ON
    SET ANSI_NULLS ON
    OLEDB和ODBC的区别
    教你认识主板上的主要芯片
    递归和迭代有什么区别
  • 原文地址:https://www.cnblogs.com/lenther2002/p/4847027.html
Copyright © 2011-2022 走看看