Entity Framework Core 实现MySQL 的TimeStamp/RowVersion 并发控制

将通用的序列号生成器库 从SQL Server迁移到Mysql 遇到的一个问题,就是TimeStamp/RowVersion并发控制类型在非Microsoft SQL Server数据库中的实现。SQL Server timestamp 数据类型与时间和日期无关。SQL Server timestamp 是二进制数字,它表明数据库中数据修改发生的相对顺序。实现 timestamp 数据类型最初是为了支持 SQL Server 恢复算法。每次修改页时,都会使用当前的 @@DBTS 值对其做一次标记,然后 @@DBTS 加1。这样做足以帮助恢复过程确定页修改的相对次序,但是 timestamp 值与时间没有任何关系。 而在MySQL中,TIMESTAMP列类型提供一种类型,你可以使用它自动地用当前的日期和时间标记INSERT或UPDATE的操作。如果你有多个TIMESTAMP列,只有第一个自动更新。

在Entity Framework 中采用IsConcurrencyToken配置后RowVersion即自动用于where子句中用于比较Row Version, 我们也需要使用这个特性实现并发控制,Ak.Ini的博文http://www.cnblogs.com/akini/archive/2013/01/30/2882767.html ,我们按照这篇文章的方法在Entity framework core上面解决并发控制问题。

定义的序列号类型:

[Table("DbServerSequence")]
   public  class DbServerSequence : ISequence
   {

       public DbServerSequence()
       {

       }
       public DbServerSequence(SequenceOptions options):this()
       {
           StartAt = options.StartAt;
           CurrentValue = StartAt;
           Increment = options.Increment;
           MaxValue = options.MaxValue;
           MinValue = options.MinValue;
           Cycle = options.Cycle;

       }

       public String Key { get; set; }
       public long StartAt { get;  set; }
       public int Increment { get;  set; }
       public long MaxValue { get;  set; }
       public long MinValue { get;  set; }
       public bool Cycle { get;  set; }
       public long CurrentValue { get; set; }

       [ConcurrencyCheck]
       public DateTime RowVersion { get; set; }

       public DateTime DateCreated { get; set; }
   }

其中RowVersion 是用作并发控制的,针对Mysql 不允许byte[]类型上标记TimeStamp/RowVersion,这里使用DateTime类型。

数据库表定义如下(自MySQL 5.6.5版本开始,DEFAULT CURRENT_TIMESTAMP 和 ON UPDATE CURRENT_TIMESTAMP 选项也可以应用到Datetime类型的列):

DROP TABLE IF EXISTS `dbserversequence`;
CREATE TABLE `dbserversequence` (
  `Key` varchar(128) NOT NULL,
  `StartAt` bigint(20) NOT NULL,
  `Increment` int(11) NOT NULL,
  `MaxValue` bigint(20) NOT NULL,
  `MinValue` bigint(20) NOT NULL,
  `Cycle` bit(1) NOT NULL,
  `CurrentValue` bigint(20) NOT NULL,
  `RowVersion` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `DateCreated` datetime NOT NULL,
  PRIMARY KEY (`Key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

在 SequenceDbContext 的OnModelCreating 重写如下,主要是配置并发控制字段:

protected override void OnModelCreating(ModelBuilder builder)
       {
           base.OnModelCreating(builder);

           builder.Entity<DbServerSequence>(e =>
           {
               e.HasKey(x => x.Key);
               e.Property(x => x.RowVersion).IsRowVersion().IsConcurrencyToken();
           });
       }

这个方案同时适用各种数据库,尤其是类似MySql和Postgresql这种不支持默认RowVersion字段的数据库。 最新的代码放在https://github.com/geffzhang/Sequence/tree/dotnetcore

本文来自合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号

时间: 2024-09-02 14:46:19

Entity Framework Core 实现MySQL 的TimeStamp/RowVersion 并发控制的相关文章

【dotnet跨平台】微软昨天宣布正式发布.NET Core RC2和.NET Core SDK Preview 1,还有Entity Framework Core RC2

 [dotnet跨平台]微软昨天宣布正式发布.NET Core RC2和.NET Core SDK Preview 1,还有Entity Framework Core RC2 期待已经的版本终于在昨天发布了 微软昨天宣布正式发布.NET Core RC2和.NET Core SDK Preview 1:https://blogs.msdn.microsoft.com/dotnet/2016/05/16/announcing-net-core-rc2/ 微软昨天宣布正式发布Entity Fra

entity framework core 更新问题

问题描述 InvalidOperationException:Theinstanceofentitytype'User'cannotbetrackedbecauseanotherinstanceofthistypewiththesamekeyisalreadybeingtracked.Whenaddingnewentities,formostkeytypesauniquetemporarykeyvaluewillbecreatedifnokeyisset(i.e.ifthekeyproperty

Entity Framework Core 实现读写分离

在之前的版本中我们可用构造函数实现,其实现在的版本也一样,之前来构造连接字符串,现在相似,构造DbContextOptions<T> 代码如下: public SContext(MasterSlave masterSlave) : base(GetOptions(masterSlave)) { // TODO: #639 //ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; } /// <sum

数据库-Entity framework 对mysql的支持在实体数据模型向导里面没有mysql

问题描述 Entity framework 对mysql的支持在实体数据模型向导里面没有mysql 快折腾我三天,求大神指导指导,有时候新建的项是的,但是是这样的 我明明引用的是mysql的为什么会出现其他的而且还没有mysql的,除了数据库不是最新的其他的中间项都是下载的最新的,求解脱···· 解决方案 是不是引用步骤不对啊,网上各有说辞,我都试过,都不能成功配置. 解决方案二: 新版的不应该这么做·····························

[Entity Framework] MySQL @ Entity Framework 6

原文 [Entity Framework] MySQL @ Entity Framework 6 要让MySQL能够用EF6,我花了一点时间,在此记录一下 安装元件 在设定档加入Provider 安装元件 从NuGet安装MySql.Data.Entities 完成后,就会看到相关元件已经被加入到专案里 接下来加入MySQL的Model 无法使用EF6 在设定档加入Provider 这时需要在App.config/Web.Config加入以下Provider,然后按下存档 < provider

mysql-使用Entity Framework链接Mysql数据库所有浮点型字段无法显示问题

问题描述 使用Entity Framework链接Mysql数据库所有浮点型字段无法显示问题 如题,不知道为何只要是Mysql中使用了浮点型字段,在EF在项目中都无法生成实体字段,不知各位大神有没有遇到过的或是解决方案,十分感谢. 解决方案 看看是不是映射的问题,两边不对应.换成decmal看看

关于MySql entity framework 6 执行like查询问题解决方案

原文:关于MySql entity framework 6 执行like查询问题解决方案 本人不善于言辞,直接开门见山 环境:EF6.0.0.0+MySQL Server5.6+MySqlConnector6.9.5.0 问题点如下: 1 var username = "admin"; 2 var lst = userService.GetQuery().Where(p => p.UserName.Contains(username)); 3 foreach (var user

Entity Framework with MySQL Provider 更新行数为0的Bug

本文将很容易解决的问题搞复杂了,多数情况下将MySql连接字符串中的Use Affected Rows参数设置为true即可. 2012-06-17 作者注.   在使用MySQL数据库来做为Entity Framework的Provider时,有时会遇到如下问题: 存储区更新.插入或删除语句影响到了意外的行数(0).实体在加载后可能被修改或删除.刷新 ObjectStateManager 项. 问题产生的场景可能为: 通常会遇到这样的问题,我们打开编辑界面,然后不更改任何内容,然后点保存,基本

MySQL &amp;amp; Entity Framework Code First 数据表大小写的问

以前都是使用Linux平台下的MySQL,现在为了调试方便,在开发机上安装了MySQL的Windows版本5.6.10,在使用Entity Framework Code First生成数据库对象时,发现所有的数据表的表名都变成了小写字符,而字段的名称是混合大小写的,这个问题在Linux平台上没有出现过,于是着手弄明白这是肿么一回事. 经过网上搜索,找到这篇文章: Entity Framework with mysql, Table Capitalization issue between lin