无需修改实体和配置,在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的价值在测试和隔离实现)

Entity Framework 6 Code First 系列:无需修改实体和配置-在MySql中使用和SqlServer一致的并发控制的更多相关文章

  1. Entity Framework 6 Code First系列1: 实体类1:1配置

    从4.1版本开始,EF开始支持Code First模式,值得注意的是Code First不是和DataBase First或Model First平级的概念,而是和EDM平级的概念.使用Code Fi ...

  2. Entity Framework 6.0 入门系列 第一篇

    Entity Framework 6.0 入门系列 第一篇 好几年前接触过一些ef感觉不是很好用,废弃.但是 Entity Framework 6.0是经过几个版本优化过的产物,性能和功能不断完善,开 ...

  3. EF(Entity Framework)系统学习系列

    好久没写博客了,继续开启霸屏模式,好了,废话不多说,这次准备重新系统学一下EF,一个偶然的机会找到了一个学习EF的网站(http://www.entityframeworktutorial.net/) ...

  4. Entity Framework 6 Code First新特性:支持存储过程

    Entity Framework 6提供支持存储过程的新特性,本文具体演示Entity Framework 6 Code First的存储过程操作. Code First的插入/修改/删除存储过程 默 ...

  5. AppBox升级进行时 - 拥抱Entity Framework的Code First开发模式

    AppBox 是基于 FineUI 的通用权限管理框架,包括用户管理.职称管理.部门管理.角色管理.角色权限管理等模块. 从Subsonic到Entity Framework Subsonic最早发布 ...

  6. Entity Framework 之 Code First

    使用NuGet助您玩转代码生成数据————Entity Framework 之 Code First [前言] 如果是Code First老鸟或者对Entity Framework不感兴趣,就不用浪费 ...

  7. Entity Framework 6 Code First的简单使用和更新数据库结构

    一.安装Entity Framework 6 在项目中右击选择“管理NuGet程序包",联机搜索Entity Framework,点击安装 二.配置数据库连接 在App.config中加入数 ...

  8. 【极力分享】[C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操作全程详细示例【转载自https://segmentfault.com/a/1190000004152660】

      [C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操作全程详细示例 本文我们来学习一下在Entity Framework中使用Cont ...

  9. 创建ASP.NET Core MVC应用程序(3)-基于Entity Framework Core(Code First)创建MySQL数据库表

    创建ASP.NET Core MVC应用程序(3)-基于Entity Framework Core(Code First)创建MySQL数据库表 创建数据模型类(POCO类) 在Models文件夹下添 ...

随机推荐

  1. Linux测试UDP端口(nc)

    # nc -vuz serveripaddress 123 Connection to serveripaddress 123 port [udp/ntp] succeeded! 结果证明UDP 12 ...

  2. C# WinForm 只运行一次的MDI子窗体

    public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void ToolColle ...

  3. 关于oracle的sequence和trigger。

    原先mysql中每个自增字段,在oracle中就需要建立一个sequence和一个trigger. 就算同一个表中有x个自增字段,那么就需要建立x个sequence和x和trigger. 实际中,我建 ...

  4. eclipse/IDEA使用maven

    下载,解压(无须安装),配置环境变量,命令行下mvn -v测试.https://www.cnblogs.com/luotaoyeah/p/3764533.html eclipse使用maven 为ec ...

  5. Pandas常用操作方法

    Pandas pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的. Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具. pandas提 ...

  6. 《深入理解Linux网络技术内幕》阅读笔记 --- 路由基本概念

    一.路由的基本概念 1.一条路由就是一组参数,这些参数存储了往一个给定目的地转发流量所需的信息,而一条路由所需的最少的参数集合为:(1)目的网络,(2)出口设备,(3)下一跳网关 2.路由中的相关术语 ...

  7. django-应用中和amdin使用富文本编辑器kindeditor

    文章描述.新闻详情和产品介绍等,都需要大量的文字描述信息或图片.视频.文字的编辑等,这个时候我们就需要介绍第三方富文本编辑器. 今天介绍的是django中绑定和应用kindeditor编辑器: 效果如 ...

  8. time 模块,random模块,os模块

    一 :time 模块 python中,通常有几种方式来表示时间: 时间戳(timestamp):通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量.我们运行“type(t ...

  9. SPL(Standard PHP Library 标准PHP类库)

    SplFileObject 读取大文件从第N行开始读: $line = 10; $splFileObj = new SplFileObject(__FILE__,'r'); $splFileObj-& ...

  10. ZOJ - 3593 One Person Game (扩展欧几里得)

    题意:一个人在坐标A,要前往坐标B的位置.可以往左或往右走a,b,a+b个单位,求到达B的最小步数. 分析:扩展欧几里得算法求解线性方程的套路不变.令C=fabs(A-B),c = a+b, 扩展gc ...