entity framework mysql guid_EntityFramework系列:MySql的RowVersion

无需修改实体和配置,在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 interfaceIRowVersion

{byte[] RowVersion { get; set; }

}

2.配置并发控制字段

protected override voidOnModelCreating(DbModelBuilder modelBuilder)

{

modelBuilder.Conventions.Remove();

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(newMySqlDbInitializer());

}

3.手动对RowVersion赋值

public override intSaveChanges()

{this.ChangeTracker.DetectChanges();var objectContext = ((IObjectContextAdapter)this).ObjectContext;foreach (ObjectStateEntry entry in objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Modified |EntityState.Added))

{var v = entry.Entity asIRowVersion;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

65267d37ca568e9ca41c0a5f5e043a06.png

6.准备测试代码

public static voidTest()

{var db1 =GetContext();var customer1 = db1.Set().FirstOrDefault();

customer1.PhoneNumber="t1";using (var db2 =GetContext())

{var customer2 = db2.Set().FirstOrDefault();

customer2.PhoneNumber= "t2";

db2.SaveChanges();

}

db1.SaveChanges();

}

7.查看测试结果:

054b8addaf963f7f78ed59124911e67e.png

总结:

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

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

这个方案同时适用各种数据库,尤其是类似MySql和Sqlite这种不支持默认RowVersion字段的数据库。希望你不是找了好久才找到这个解决方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值