Pomelo.entityframeworkcore.mysql: 当表具有默认值 CURRENT_TIMESTAMP 的日期时间/时间戳列时,数据库脚手架会产生错误的代码

创建于 2018-10-31  ·  3评论  ·  资料来源: PomeloFoundation/Pomelo.EntityFrameworkCore.MySql

重现步骤

创建一个这样的表:

create table TimestampTable(
    Id int not null,
    Ts timestamp default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
    Dt datetime default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
    primary key (Id)
);

跑步:

dotnet ef dbcontext scaffold \
    --data-annotations \
    --context TestDb \
    --force \
    --use-database-names \
    "my_connection_string" \
    "Pomelo.EntityFrameworkCore.MySql"

问题

Pomelo 设置默认值'CURRENT_TIMESTAMP' (字符串)而不是CURRENT_TIMESTAMP

生成的代码是:
```c#
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
模型构建器.Entity(实体=>
{
entity.Property(e => e.Dt)
.HasDefaultValueSql("'CURRENT_TIMESTAMP'") // <-- 问题
.ValueGeneratedOnAddOrUpdate();

            entity.Property(e => e.Ts)
                .HasDefaultValueSql("'CURRENT_TIMESTAMP'") // <-- problem
                .ValueGeneratedOnAddOrUpdate();
        });
    }
Trying to recreate the database with `myDbContext.Database.EnsureCreated()` will throw an exception 
because the default value for the `timestamp` column is `'CURRENT_TIMESTAMP'`.

EFCore Log:

信息:Microsoft.EntityFrameworkCore.Infrastructure[10403]
Entity Framework Core 2.1.2-rtm-30932 使用提供程序“Pomelo.EntityFrameworkCore.MySql”初始化“TestDb”,选项:无
信息:Microsoft.EntityFrameworkCore.Database.Command[20101]
执行 DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
创建数据库TestDb_EFCore ;
失败:Microsoft.EntityFrameworkCore.Database.Command[20102]
执行 DbCommand 失败 (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
创建表TimestampTable (
Id int(11) NOT NULL AUTO_INCREMENT,
Ts时间戳 NOT NULL DEFAULT 'CURRENT_TIMESTAMP',
Dt日期时间 NULL DEFAULT 'CURRENT_TIMESTAMP',
约束PK_TimestampTable主键 ( Id )
);

Exception message:

MySql.Data.MySqlClient.MySqlException (0x80004005): 'Ts' 的默认值无效

Stack trace:

MySql.Data.MySqlClient.MySqlException (0x80004005): 'Ts' 的默认值无效 ---> MySql.Data.MySqlClient.MySqlException (0x80004005): 'Ts' 的默认值无效
在 MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior ioBehavior) 在 C:\projects\mysqlconnector\src\MySqlConnector\Core\ResultSet.cs:line 42
在 MySql.Data.MySqlClient.MySqlDataReader.ActivateResultSet(ResultSet resultSet) 在 C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlDataReader.cs:line 74
在 MySql.Data.MySqlClient.MySqlDataReader.ReadFirstResultSetAsync(IOBehavior ioBehavior) 在 C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlDataReader.cs:line 299
在 MySql.Data.MySqlClient.MySqlDataReader.CreateAsync(MySqlCommand 命令,CommandBehavior 行为,ResultSetProtocol resultSetProtocol,IOBehavior ioBehavior) 在 C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlDataReader.cs:line 284
在 MySqlConnector.Core.TextCommandExecutor.ExecuteReaderAsync(String commandText, MySqlParameterCollection parameterCollection, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancelationToken) 在 C:\projects\mysqlconnector\src\MySqlConnector\Core\TextCommandExecutor.cs:line 37
在 C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlCommand.cs:line 261 中的 MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQueryAsync(IOBehavior ioBehavior, CancellationToken cancelationToken)
在 MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQuery() 在 C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlCommand.cs:line 62
在 Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, DbCommandMethod executeMethod, IReadOnlyDictionary`2 parameterValues)

未处理的异常:MySql.Data.MySqlClient.MySqlException:“Ts”的默认值无效 ---> MySql.Data.MySqlClient.MySqlException:“Ts”的默认值无效
在 MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior ioBehavior) 在 C:\projects\mysqlconnector\src\MySqlConnector\Core\ResultSet.cs:line 42
--- 内部异常堆栈跟踪结束 ---
在 MySql.Data.MySqlClient.MySqlDataReader.ActivateResultSet(ResultSet resultSet) 在 C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlDataReader.cs:line 74
在 MySql.Data.MySqlClient.MySqlDataReader.ReadFirstResultSetAsync(IOBehavior ioBehavior) 在 C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlDataReader.cs:line 299
在 MySql.Data.MySqlClient.MySqlDataReader.CreateAsync(MySqlCommand 命令,CommandBehavior 行为,ResultSetProtocol resultSetProtocol,IOBehavior ioBehavior) 在 C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlDataReader.cs:line 284
在 MySqlConnector.Core.TextCommandExecutor.ExecuteReaderAsync(String commandText, MySqlParameterCollection parameterCollection, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancelationToken) 在 C:\projects\mysqlconnector\src\MySqlConnector\Core\TextCommandExecutor.cs:line 37
在 C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlCommand.cs:line 261 中的 MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQueryAsync(IOBehavior ioBehavior, CancellationToken cancelationToken)
在 MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQuery() 在 C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlCommand.cs:line 62
在 Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection 连接,DbCommandMethod executeMethod,IReadOnlyDictionary 2 parameterValues) at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteNonQuery(IRelationalConnection connection, IReadOnlyDictionary 2 参数值)
在 Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.ExecuteNonQuery(IEnumerable`1 migrationCommands, IRelationalConnection 连接)
在 Microsoft.EntityFrameworkCore.Storage.RelationalDatabaseCreator.EnsureCreated()
在 CreateDb.Program.Main(String[] args) 在 /git/netcore-planet-garavot8-data/CreateDb/Program.cs:line 30
``

更多技术细节

MySQL 版本: 5.7.20
操作系统: CentOS 7.4
Pomelo.EntityFrameworkCore.MySql 版本: 2.1.2

type-bug

最有用的评论

MySqlDatabaseModelFactory类中默认值的逻辑目前是基本的,因为它假定默认值是一个字符串。

将需要类型检查,即 varchar、int、enum 等,以确定是否需要引号(并在需要时使用转义)并遵循数据类型默认值中的规则。

所有3条评论

MySqlDatabaseModelFactory类中默认值的逻辑目前是基本的,因为它假定默认值是一个字符串。

将需要类型检查,即 varchar、int、enum 等,以确定是否需要引号(并在需要时使用转义)并遵循数据类型默认值中的规则。

已在 #896 中修复。

我发现下面的代码可以正常工作并在新版本发布之前避免错误。
```C#
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
模型构建器.Entity(实体=>
{
entity.Property(e => e.Dt)
.HasDefaultValueSql("CURRENT_TIMESTAMP()")
.ValueGeneratedOnAddOrUpdate();

            entity.Property(e => e.Ts)
                .HasDefaultValueSql("CURRENT_TIMESTAMP()")
                .ValueGeneratedOnAddOrUpdate();
        });
    }

``

此页面是否有帮助?
0 / 5 - 0 等级