zoukankan      html  css  js  c++  java
  • 针对Mysql 使用EF Code First时 TimeStamp/RowVersion 类型 的解决办法

    环境:

    mysql5.5

    .Net Connector 6.6.4

    EF 4.3.1

    模型要求:

    很多业务要求并发处理,时间戳是个很好的选择.

    代码如下:

        public class Test
        {
            public int ID { get; set; }
            public string Name { get; set; }
            public byte[] LastChanged { get; set; }
        }
    

      

    问题描述:在LastChanged属性用Data Annotations标记[Timestamp]

    [Timestamp]
    public byte[] LastChanged { get; set; }
    

    或者Fluent API中配置成IsRowVersion()

    DbModelBuilder 作如下配置

    modelBuilder.Entity<Test>().Property(p => p.LastChanged).IsRowVersion();
    

    或者EnityTypeConfiguration<T>类中配置

    Property(p=>p.LastChanged).IsRowVersion();

    在Migration的时候 会有错误,如下:

    错误 0040: 类型 rowversion 未使用命名空间或别名进行限定。只有 PrimitiveType 才可以在不限定的情况下使用。

    原因是 MySqlMigrationSqlGenerator不允许byte[]类型上标记TimeStamp/RowVersion

    那应该用什么类型?

    database first来看看 这里就不截图 加表 设置字段类型 TIMESTAMP 默认值 CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

    生成EDM 类型 为Datetime 这和MsSql是有区别的

    现在修改模型

    public class Test
        {
            public int ID { get; set; }
            public string Name { get; set; }
            public DateTime LastChanged { get; set; }
        }
    

    编译下代码 不能通过 EF的.IsRowVersion()方法不能作用于DateTime类型的属性.

    修改DbModelBuilder代码:

    Property(p => p.LastChanged).IsConcurrencyToken();

    再次Migration 并且 update-database 去查看数据库的表结构

    问题又来了 LastChanged的数据库类型成Datetime了

    我们手动来解决这个问题

    修改DbMigration中的Up方法的代码

    源代码如下:

    AddColumn("Tests", "LastChanged", c => c.DateTime(nullable: false);
    

    修改为

    AddColumn("Tests", "LastChanged", c => c.DateTimeOffset(nullable: false, defaultValueSql: "CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"));
    

    update-database后 检查表结构 ok!没有问题了

    测试下

    using (var db = new BlogContext())
    {
        db.Tests.Add(new Test { Name = "Test01" });
        db.SaveChanges();
    }
    

    是不是又异常了 看详细信息 原来把LastChanged字段的值更新回数据库了 这不是我们预期了

    再去修改下DbModelBuilder代码:

    Property(p => p.LastChanged).IsConcurrencyToken().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    

    再测试 ok! 通过

    以上代码是成功后再添加的 如有问题 请指出

    再来总结下mysql下使用code first时 时间戳类型 要注意的几点

    1.模型中的类型 必须为datetime

    2.使用IsConcurrencyToken()方法

    3.up脚本修改 AddColumn("Tests", "LastChanged", c => c.DateTimeOffset(nullable: false, defaultValueSql: "CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"));

    4.使用.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)方法

    打完收工

    另外 

    如其他数据库时间戳类型映射模型时的类型不为byte[]时 都可以用此方法来解决 

    ef版本也不限于4.3.1 (没有测试)

    请其他使用高版本ef并且使用其他数据库的TX 帮忙测试

  • 相关阅读:
    mybatis+sql语句
    坐标转换
    sql语句含中文JDBC查询不到
    架构阅读笔记16
    架构阅读笔记15
    架构阅读笔记14
    windows安装imgaug包报错中Shapely
    java除法
    Java输入输出问题复习
    java自学,基础,入门
  • 原文地址:https://www.cnblogs.com/akini/p/2882767.html
Copyright © 2011-2022 走看看