Pomelo.entityframeworkcore.mysql: O scaffolding do banco de dados produz código errado quando as tabelas têm colunas datetime / timestamp com valor padrão CURRENT_TIMESTAMP

Criado em 31 out. 2018  ·  3Comentários  ·  Fonte: PomeloFoundation/Pomelo.EntityFrameworkCore.MySql

Passos para reproduzir

Crie uma tabela como esta:

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)
);

corre:

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

O problema

Pomelo define o valor padrão 'CURRENT_TIMESTAMP' (string) em vez de CURRENT_TIMESTAMP

O código gerado é:
`` `c #
protected override void OnModelCreating (ModelBuilder modelBuilder)
{
modelBuilder.Entity(entidade =>
{
entidade.Propriedade (e => e.Dt)
.HasDefaultValueSql ("'CURRENT_TIMESTAMP'") // <- problema
.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:

informações: Microsoft.EntityFrameworkCore.Infrastructure [10403]
Entity Framework Core 2.1.2-rtm-30932 inicializado 'TestDb' usando o provedor 'Pomelo.EntityFrameworkCore.MySql' com opções: Nenhum
informações: Microsoft.EntityFrameworkCore.Database.Command [20101]
DbCommand executado (3ms) [Parameters = [], CommandType = 'Text', CommandTimeout = '30 ']
CRIAR BANCO DE DADOS TestDb_EFCore ;
falha: Microsoft.EntityFrameworkCore.Database.Command [20102]
Falha ao executar DbCommand (1ms) [Parameters = [], CommandType = 'Text', CommandTimeout = '30 ']
CRIAR TABELA TimestampTable (
Id int (11) NÃO NULO AUTO_INCREMENT,
Ts timestamp NOT NULL DEFAULT 'CURRENT_TIMESTAMP',
Dt datetime NULL DEFAULT 'CURRENT_TIMESTAMP',
RESTRIÇÃO PK_TimestampTable CHAVE PRIMÁRIA ( Id )
);

Exception message:

MySql.Data.MySqlClient.MySqlException (0x80004005): Valor padrão inválido para 'Ts'

Stack trace:

MySql.Data.MySqlClient.MySqlException (0x80004005): Valor padrão inválido para 'Ts' ---> MySql.Data.MySqlClient.MySqlException (0x80004005): Valor padrão inválido para 'Ts'
em MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync (IOBehavior ioBehavior) em C: \ projects \ mysqlconnector \ src \ MySqlConnector \ Core \ ResultSet.cs: linha 42
em MySql.Data.MySqlClient.MySqlDataReader.ActivateResultSet (ResultSet resultSet) em C: \ projects \ mysqlconnector \ src \ MySqlConnector \ MySql.Data.MySqlClient \ MySqlDataReader.cs: linha 74
em MySql.Data.MySqlClient.MySqlDataReader.ReadFirstResultSetAsync (IOBehavior ioBehavior) em C: \ projects \ mysqlconnector \ src \ MySqlConnector \ MySql.Data.MySqlClient \ MySqlDataReader.cs: linha 299
em MySql.Data.MySqlClient.MySqlDataReader.CreateAsync (comando MySqlCommand, comportamento de CommandBehavior, ResultSetProtocol resultSetProtocol, IOBehavior ioBehavior) em C: \ projects \ mysqlCommand \ src \ MySqlConnector \ src \ MySqlConnector \ src \ MySqlConnector \ src \ MySqlConnector \ src \ MySqlConnector \ src \ MySqlConnector \ src \ MySqleadM line.
em MySqlConnector.Core.TextCommandExecutor.ExecuteReaderAsync (String commandText, MySqlParameterCollection parameterCollection, CommandBehavior behaviour, IOBehavior ioBehavior, CancelToken cancellationToken) em C: \ projects \ mysqlconnector \ src \ Linha de MySqlConnector \ Core \ Text \ MySqlConnector \ CoreEx
em MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQueryAsync (IOBehavior ioBehavior, CancelToken cancellationToken) em C: \ projects \ mysqlconnector \ src \ MySqlConnector \ MySql.Data.MySqlClient \ MySqlCommand.cs: linha 261
em MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQuery () em C: \ projects \ mysqlconnector \ src \ MySqlConnector \ MySql.Data.MySqlClient \ MySqlCommand.cs: linha 62
em Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute (conexão IRelationalConnection, DbCommandMethod executeMethod, IReadOnlyDictionary`2 parameterValues)

Exceção não tratada: MySql.Data.MySqlClient.MySqlException: Valor padrão inválido para 'Ts' ---> MySql.Data.MySqlClient.MySqlException: Valor padrão inválido para 'Ts'
em MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync (IOBehavior ioBehavior) em C: \ projects \ mysqlconnector \ src \ MySqlConnector \ Core \ ResultSet.cs: linha 42
--- Fim do rastreamento de pilha de exceção interna ---
em MySql.Data.MySqlClient.MySqlDataReader.ActivateResultSet (ResultSet resultSet) em C: \ projects \ mysqlconnector \ src \ MySqlConnector \ MySql.Data.MySqlClient \ MySqlDataReader.cs: linha 74
em MySql.Data.MySqlClient.MySqlDataReader.ReadFirstResultSetAsync (IOBehavior ioBehavior) em C: \ projects \ mysqlconnector \ src \ MySqlConnector \ MySql.Data.MySqlClient \ MySqlDataReader.cs: linha 299
em MySql.Data.MySqlClient.MySqlDataReader.CreateAsync (comando MySqlCommand, comportamento de CommandBehavior, ResultSetProtocol resultSetProtocol, IOBehavior ioBehavior) em C: \ projects \ mysqlCommand \ src \ MySqlConnector \ src \ MySqlConnector \ src \ MySqlConnector \ src \ MySqlConnector \ src \ MySqlConnector \ src \ MySqlConnector \ src \ MySqleadM line.
em MySqlConnector.Core.TextCommandExecutor.ExecuteReaderAsync (String commandText, MySqlParameterCollection parameterCollection, CommandBehavior behaviour, IOBehavior ioBehavior, CancelToken cancellationToken) em C: \ projects \ mysqlconnector \ src \ Linha de MySqlConnector \ Core \ Text \ MySqlConnector \ CoreEx
em MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQueryAsync (IOBehavior ioBehavior, CancelToken cancellationToken) em C: \ projects \ mysqlconnector \ src \ MySqlConnector \ MySql.Data.MySqlClient \ MySqlCommand.cs: linha 261
em MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQuery () em C: \ projects \ mysqlconnector \ src \ MySqlConnector \ MySql.Data.MySqlClient \ MySqlCommand.cs: linha 62
em Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute (conexão IRelationalConnection, DbCommandMethod executeMethod, IReadOnlyDictionary 2 parameterValues) at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteNonQuery(IRelationalConnection connection, IReadOnlyDictionary 2 parameterValues)
em Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.ExecuteNonQuery (IEnumerable`1 migrationCommands, conexão IRelationalConnection)
em Microsoft.EntityFrameworkCore.Storage.RelationalDatabaseCreator.EnsureCreated ()
em CreateDb.Program.Main (String [] args) em /git/netcore-planet-garavot8-data/CreateDb/Program.cs: linha 30
`` `

Mais detalhes técnicos

Versão MySQL: 5.7.20
Sistema operacional: CentOS 7.4
Pomelo.EntityFrameworkCore.MySql versão: 2.1.2

type-bug

Comentários muito úteis

A lógica para padrões na classe MySqlDatabaseModelFactory é atualmente rudimentar, pois assume que o padrão é uma string.

A verificação de tipo será necessária, ou seja, varchar, int, enum etc. para determinar se as aspas são necessárias (e para usar escape, se necessário) e também seguir as regras em Valores padrão de tipo de dados .

Todos 3 comentários

A lógica para padrões na classe MySqlDatabaseModelFactory é atualmente rudimentar, pois assume que o padrão é uma string.

A verificação de tipo será necessária, ou seja, varchar, int, enum etc. para determinar se as aspas são necessárias (e para usar escape, se necessário) e também seguir as regras em Valores padrão de tipo de dados .

Corrigido em # 896.

Acho que os códigos abaixo podem funcionar bem e evitar o bug antes do lançamento de novas versões.
`` `C #
protected override void OnModelCreating (ModelBuilder modelBuilder)
{
modelBuilder.Entity(entidade =>
{
entidade.Propriedade (e => e.Dt)
.HasDefaultValueSql ("CURRENT_TIMESTAMP ()")
.ValueGeneratedOnAddOrUpdate ();

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

`` `

Esta página foi útil?
0 / 5 - 0 avaliações