dotnetcore / FreeSql

🦄 .NET aot orm, C# orm, VB.NET orm, Mysql orm, Postgresql orm, SqlServer orm, Oracle orm, Sqlite orm, Firebird orm, 达梦 orm, 人大金仓 orm, 神通 orm, 翰高 orm, 南大通用 orm, 虚谷 orm, 国产 orm, Clickhouse orm, QuestDB orm, MsAccess orm.
http://freesql.net
MIT License
4.08k stars 849 forks source link

MySql CodeFirst生成的更新列默认值utc_timestamp不被mysql支持 #1604

Closed houlongchao closed 9 months ago

houlongchao commented 1 year ago

CodeFirst生成的脚本MySql脚本执行报错:

ALTER TABLE `t_param_item` ADD `update_time` DATETIME(3) NOT NULL DEFAULT utc_timestamp(3) COMMENT '修改时间  [UTC]';
> 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'utc_timestamp(3) COMMENT '修改时间  [UTC]'' at line 1

utc_timestamp(3)修改为current_timestamp(3)就可以了。 mysql在设置默认时间时不支持utc_timestamp

2881099 commented 1 year ago

如果是非 utc 时区,用 current_timestamp 就不对了呀

2881099 commented 1 year ago

数据库使用的什么版本

2881099 commented 1 year ago

实体特性使用了 [Column(ServerTime = DateTimeKind.Utc] 就会触发上述建表内容

houlongchao commented 1 year ago

测试了5.7.31和8.0.13,都执行自动生成的代码设置utc默认值的代码报错。

2881099 commented 1 year ago

我这里正常,你用的是mysql吗

2881099 commented 1 year ago

select utc_timestamp

执行看看

houlongchao commented 1 year ago

这就奇了怪了 image

2881099 commented 1 year ago

select utc_timestamp(3)

这样呢

houlongchao commented 1 year ago

一样的。 image

2881099 commented 1 year ago

alter 把 utc_timestamp(3) 加上双引号试试

2881099 commented 1 year ago

单引号也试试

houlongchao commented 1 year ago

不行,还是报错,加了引号后就成字符串了,没法赋值给日期时间。 找了个在线测试环境也是一样。

https://www.db-fiddle.com/ image

2881099 commented 1 year ago

要不把特性改成 [Column(ServerTime = DateTimeKind.Local]

houlongchao commented 1 year ago

这是mysql的一个bug,mysql就不支持更新utc_timestamp. 而且这个bug一直没有修。https://bugs.mysql.com/bug.php?id=103228#:~:text=You%20have%20an%20error%20in%20your%20SQL%20syntax%3B,setting%2C%20should%20also%20be%20allowed%20for%20ON%20UPDATE.

建议将mysql生成的脚本暂时改为current_timestamp比较好,确保脚本不会报错,不然现在生成的就是一个错误的脚本不是很好。

2881099 commented 1 year ago

v3.2.705

blueHF commented 11 months ago

在 FreeSql 3.2.669 还是正常, 这两天升级为 3.2.800 后发现这个情况 ps: 数据库版本和代码没有改动的情况下,只升级FreeSql 的版本

v3.2.705

2881099 commented 11 months ago

你们两个的数据库版本一致吗

blueHF commented 11 months ago

同一个环境的,  数据库版本是一致的这两天只是把nuget 包更新了,发布后发现了这个问题

blueHF commented 11 months ago

image

截图的 id 900900 数据是 3.2.669 执行后的数据 截图的 id 900899 数据是 3.2.800 执行后的数据 特意回滚测试了下功能 数据库版本: image

nuget 信息: 升级前

        <PackageReference Include="FreeSql.All" Version="3.2.669" />
    <PackageReference Include="FreeSql.Provider.Firebird" Version="3.2.669" />
    <PackageReference Include="FreeSql.Provider.KingbaseES" Version="3.2.669" />
    <PackageReference Include="FreeSql.Provider.ShenTong" Version="3.2.669" />

升级后

    <PackageReference Include="FreeSql.All" Version="3.2.800" />
    <PackageReference Include="FreeSql.Provider.Firebird" Version="3.2.800" />
    <PackageReference Include="FreeSql.Provider.KingbaseES" Version="3.2.800" />
    <PackageReference Include="FreeSql.Provider.ShenTong" Version="3.2.800" />

模型的代码片段

   [Table(Name = "tbl_plat_company")]
    public class MTenant : IModel
    {
        /// <summary>
        /// Id
        /// </summary>
        [Column(Name = "id", IsPrimary = true, IsIdentity = true, IsNullable = false, CanUpdate = false)]
        public long Id { get; set; }

        /// <summary>
        /// 名称
        /// </summary>
        [Column(Name = "name", StringLength = 31, IsNullable = false)]
        public string Name { get; set; }

        /// <summary>
        /// 创建时间
        /// </summary>
        [Column(Name = "create_time", IsNullable = false, CanUpdate = false, ServerTime = DateTimeKind.Utc)]
        public DateTime CreateTime { get; set; }
   }

CodeFirst 写法片段:

using (var conn = rd.GetConnection())
                {
                    Logger.LogInformation($"数据库连接字符串:{conn.Ado.MasterPool.Get(TimeSpan.FromSeconds(5)).Value.ConnectionString}");

                        Parallel.ForEach(types, item =>
                        {
                            conn.CodeFirst.SyncStructure(item);
                        });                       

                    Logger.LogInformation($"同步数据库结构——完成");
                }

新增的写法代码片段

using (var conn = RepositoryDirector.GetConnection())
            {
                var result = 0L;
                conn.Transaction(() =>
                {
                    result = conn.Insert(tenant).ExecuteIdentity();
                });
                return result;
            }
blueHF commented 11 months ago

数据库镜像: mysql:5.7.38 数据库配置:

[mysql]
default-character-set = utf8mb4
[mysql.server]
default-character-set = utf8mb4
[client]
default-character-set = utf8mb4
[mysqld]
# 主配置
port = 3306
general_log=0
log-error=/var/lib/mysql/error.log
server_id=100
master_info_repository=TABLE
relay_log_info_repository=TABLE
lower_case_table_names=1

transaction_write_set_extraction=XXHASH64

binlog_format=row
binlog_checksum=none
gtid_mode=on
enforce_gtid_consistency=on
log_slave_updates=on
binlog_format=row
log_bin=/var/lib/mysql/binlog
## 开启二进制日志功能,可以随便取,最好有含义(关键就是这里了)
#log-bin=replicas-mysql-bin
## 为每个session分配的内存,在事务过程中用来存储二进制日志的缓存
binlog_cache_size=1M
## 二进制日志自动删除/过期的天数。默认值为0,表示不自动删除。
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
## relay_log配置中继日志
relay_log=replicas-mysql-relay-bin
## log_slave_updates表示slave将复制事件写进自己的二进制日志
log_slave_updates=1

default-time_zone = '+08:00'
character_set_server = utf8mb4
max_connections = 4000
transaction_isolation = READ-COMMITTED
max_allowed_packet = 1073741824
wait_timeout = 86400
interactive_timeout = 86400
2881099 commented 11 months ago

对的,我自己测试5.6也是好的,你看上面别人提的问题,他是mysql8,看来需要抽出来单独配置这个了

2881099 commented 11 months ago

这个问题, [Column(ServerTime = DateTimeKind.Utc] ,仍然采用 utc_timestamp 函数

迁移结果时产生的 alter table 语句不产生 set default 片段。

@houlongchao

v3.2.800 已下架了,避免更多我爱影响,重新发布了 v3.2.801