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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏禅林阆苑

mysql学习总结04 — SQL数据操作

mysql 中 SELECT 命令类似于其他编程语言的 print 或 write,可用来显示字符串、数字、数学表达式的结果等

29130
来自专栏Java技术栈

去BAT面试完的Mysql面试题总结(55道,带完整答案)

55道互联网大公司的经典面试题,全部答对月薪5W+没问题。 1、一张表里面有ID自增主键,当insert了17条记录之后,删除了第15,16,17条记录,再把m...

1.7K50
来自专栏一个爱吃西瓜的程序员

学习SQL【2】-数据库与SQL

一:数据库是什么? 1:定义 ● 将大量数据通过计算机加工而成的可以进行高效访问的数据集合称为数据库(DB)。 ● 用来管理数据库的计算机系统称为数据库管理系...

37090
来自专栏吴伟祥

Navicat Premium 技巧介绍 + MySQL性能分析

注:数据库里的数据顺序是按照创建时间存储并排序的,对应List的元素索引从小到大,即索引值越大,这条数据的创建时间越晚,与数据库里的顺序是对应的。 (默认...

47720
来自专栏Danny的专栏

《高性能 MySQL》读书笔记

1、隔离级别有四种: READ UNCOMMITTED(未提交读),同事务中某个语句的修改,即使没有提交,对其他事务也是可见的。这个也叫脏读。 READ...

21820
来自专栏云计算教程系列

如何管理SQL数据库

安装SQL数据库时,需要添加,修改,删除和查询数据所需的所有命令。这个备忘单样式指南提供了一些最常用的SQL命令的快速参考。

26820
来自专栏lestat's blog

mysql开发规范

命名规范 库名、表名、字段名必须使用小写字母,并采用下划线分割 库名、表名、字段名禁用超过32个字符。须见名知意 库名、表名、字段名禁用使 MySQL保留字 临...

468170
来自专栏吾爱乐享

软件测试之学习mysql的增删改(数据库重点)

14120
来自专栏互联网技术栈

MySQL EXPLAIN详解

MySQL EXPLAIN命令是查询性能优化不可缺少的一部分,该文主要讲解explain命令的使用及相关参数说明。

17490
来自专栏java一日一条

InnoDB引擎算法和优化

索引是应用程序设计和开发的一个重要方面。如果索引太多,应用的性能可能会受到影响;如果索引太少,对查询性能又会产生影响。

11010

扫码关注云+社区

领取腾讯云代金券