EF在MySql数据库中重命名列

时间:2018-03-03 04:20:30

标签: c# mysql entity-framework

我正在尝试通过MySql数据库中的迁移重命名列。

这是我的迁移:

public override void Up()
{
   //RenameColumn("Docks", "ProfileId", "SecondId"); <!-- doesn't work either
   RenameColumn("Docks", "ProfileId", "SecondId", anonymousArguments: new { ColumnType = "int" });
}

public override void Down()
{
   //RenameColumn("Docks", "SecondId", "ProfileId"); <!-- doesn't work either
   RenameColumn("Docks", "SecondId", "ProfileId", anonymousArguments:  new { ColumnType = "int" });
}

当我运行Update-Database时,它会向我发出一个大错误(如果您想查看整个错误,请打开代码段),其中包括:

  

MySql.Data.MySqlClient.MySqlException(0x80004005):必须定义参数'@columnType'。

MySql.Data.MySqlClient.MySqlException(0x80004005): Fatal error encountered during command execution.-- - > MySql.Data.MySqlClient.MySqlException(0x80004005): Parameter '@columnType' must be defined. at MySql.Data.MySqlClient.Statement.SerializeParameter(MySqlParameterCollection
parameters, MySqlPacket packet, String parmName, Int32 parameterIndex) at MySql.Data.MySqlClient.Statement.InternalBindParameters(String sql, MySqlParameterCollection parameters, MySqlPacket packet) at MySql.Data.MySqlClient.Statement.BindParameters()
at MySql.Data.MySqlClient.PreparableStatement.Execute() at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior) at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior) at MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQuery()
at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.
< NonQuery> b__0(DbCommand t, DbCommandInterceptionContext `1 c) at System.Data.Entity.Infrastructure.Interception.InternalDispatcher` 1. Dispatch[TTarget, TInterceptionContext, TResult](TTarget target, Func `3 operation, TInterceptionContext interceptionContext,
  Action` 3 executing, Action `3 executed) at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.NonQuery(DbCommand command, DbCommandInterceptionContext interceptionContext) at System.Data.Entity.Internal.InterceptableDbCommand.ExecuteNonQuery()
  at System.Data.Entity.Migrations.DbMigrator.ExecuteSql(MigrationStatement migrationStatement, DbConnection connection, DbTransaction transaction, DbInterceptionContext interceptionContext) at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ExecuteSql(MigrationStatement
  migrationStatement, DbConnection connection, DbTransaction transaction, DbInterceptionContext interceptionContext) at System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable` 1 migrationStatements, DbConnection connection, DbTransaction
  transaction, DbInterceptionContext interceptionContext) at System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsWithinTransaction(IEnumerable `1 migrationStatements, DbTransaction transaction, DbInterceptionContext interceptionContext) at System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsWithinNewTransaction(IEnumerable`
  1 migrationStatements, DbConnection connection, DbInterceptionContext interceptionContext) at System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable `1 migrationStatements, DbConnection connection, DbInterceptionContext interceptionContext)
  at System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable` 1 migrationStatements, DbConnection connection) at System.Data.Entity.Migrations.DbMigrator.
  <> c__DisplayClass32.
    < ExecuteStatements> b__30() at System.Data.Entity.Infrastructure.DefaultExecutionStrategy.Execute(Action operation) at System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable `1 migrationStatements, DbTransaction existingTransaction) at System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable`
      1 migrationStatements) at System.Data.Entity.Migrations.Infrastructure.MigratorBase.ExecuteStatements(IEnumerable `1 migrationStatements) at System.Data.Entity.Migrations.DbMigrator.ExecuteOperations(String migrationId, VersionedModel targetModel,
      IEnumerable` 1 operations, IEnumerable `1 systemOperations, Boolean downgrading, Boolean auto) at System.Data.Entity.Migrations.DbMigrator.ApplyMigration(DbMigration migration, DbMigration lastMigration) at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ApplyMigration(DbMigration
      migration, DbMigration lastMigration) at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable` 1 pendingMigrations, String targetMigrationId, String lastMigrationId) at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable
      `1 pendingMigrations, String targetMigrationId, String lastMigrationId) at System.Data.Entity.Migrations.DbMigrator.UpdateInternal(String targetMigration) at System.Data.Entity.Migrations.DbMigrator.
      <>c__DisplayClasse.
        <Update>b__d() at System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(Action mustSucceedToKeepDatabase) at System.Data.Entity.Migrations.Infrastructure.MigratorBase.EnsureDatabaseExists(Action mustSucceedToKeepDatabase) at System.Data.Entity.Migrations.DbMigrator.Update(String
          targetMigration) at System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(String targetMigration) at System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.RunCore() at System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.Run()
          Fatal error encountered during command execution.

详细模式在抛出错误之前生成了以下sql查询:

set @columnType := (select  case lower(IS_NULLABLE)
                            when 'no' then CONCAT(column_type, ' not null ')
                            when 'yes' then column_type end
    from  information_schema.columns
    where  table_name = 'Docks'
      and  column_name = 'ProfileId');
set @sqlstmt := (select concat('alter table `Docks`
                      change `ProfileId` `SecondId` ' , @columnType));
prepare stmt from @sqlstmt;
execute stmt;
deallocate prepare stmt;

我很好奇,所以我将sql复制并粘贴到数据库中,并按预期执行而没有错误,并成功地重命名了具有正确类型int(11)的列。

那么,即使它生成(显然)有效的sql,我该如何防止这个错误抛出?

编辑:想要注意这里接受的答案对我有用,即使我没有使用dotconnect。

3 个答案:

答案 0 :(得分:3)

找到上述问题的解决方案:(MySql.Data.MySqlClient.MySqlException):据我所知,它与连接器的升级有关。

您需要在连接字符串中添加Allow User Variables=True才能使用自定义变量。

请点击此链接以供参考:

http://blog.tjitjing.com/index.php/2009/05/mysqldatamysqlclientmysqlexception-parameter-id-must-be-defined.html

答案 1 :(得分:0)

上下采用相同的列类型。我假设您只想更改列名称。我想你可以尝试没有像这样的匿名参数:

public override void Up()
{
    // RenameColumn("Docks", "ProfileId", "SecondId"); // old answer
    RenameColumn("Docks", "ProfileId", "SecondId", anonymousArguments: new { columnType = "int" });
}

public override void Down()
{
    // RenameColumn("Docks", "SecondId", "ProfileId"); // old answer
    RenameColumn("Docks", "SecondId", "ProfileId", anonymousArguments: new { columnType = "int" });
}

答案 2 :(得分:0)

ALTERing列时,您必须指定整个定义,而不仅仅是您要更改的内容。你遗漏了数据类型(INT),可能还有其他东西。

我建议您获取SHOW CREATE TABLE的输出,修改相关的一行,然后在ALTER中使用该输出。虽然很乱,但它可能比试图重建有关领域的完整描述更容易。

在实践中,手动执行任务更容易,而不是以编程方式执行。