Pomelo.EntityFrameworkCore.MySql icon indicating copy to clipboard operation
Pomelo.EntityFrameworkCore.MySql copied to clipboard

Error adding integer auto-increment column with migration (since 8.0.1)

Open atsidaev opened this issue 2 months ago • 0 comments

Steps to reproduce

Here is the minimal reproducible example. Use an empty database and the following data context:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
public class ApplicationDbContext : DbContext
{
	public DbSet<User> Users { get; set; }
	protected override void OnConfiguring(DbContextOptionsBuilder modelBuilder)
	{
		var connectionString = "..."; 
		modelBuilder.UseMySql(
			connectionString,
			ServerVersion.AutoDetect(connectionString));
	}
}
public class User
{
	[Key]
	[Required, MaxLength(32)]
	public string Name { get; set; }
}

Create initial migration

dotnet ef migrations add Migration1

Change User class this way (i.e. remove an old key and add new auto-incremented integer key field)

public class User
{
	[Required, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
	public int Id { get; set; }
	[Required, MaxLength(32)]
	public string Name { get; set; }
}

Add migration:

dotnet ef migrations add Migration2

Now attempt to create the table in the database:

dotnet ef database update

An error is occurred. This happens starting from 8.0.1 version of Pomelo.EntityFrameworkCore.MySql. 8.0.0 works as expected.

The issue

This is the log with the exception:

Applying migration '20240425143650_Migration1'.
Applying migration '20240425143716_Migration2'.
Failed executing DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
ALTER TABLE `Users` ADD `Id` int NOT NULL DEFAULT 0 AUTO_INCREMENT,
ADD CONSTRAINT `PK_Users` PRIMARY KEY (`Id`);
MySqlConnector.MySqlException (0x80004005): Invalid default value for 'Id'
   at MySqlConnector.Core.ServerSession.ReceiveReplyAsync(IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/Core/ServerSession.cs:line 894
   at MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior ioBehavior) in /_/src/MySqlConnector/Core/ResultSet.cs:line 37
   at MySqlConnector.MySqlDataReader.ActivateResultSet(CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 130
   at MySqlConnector.MySqlDataReader.InitAsync(CommandListPosition commandListPosition, ICommandPayloadCreator payloadCreator, IDictionary`2 cachedProcedures, IMySqlCommand command, CommandBehavior behavior, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 483
   at MySqlConnector.Core.CommandExecutor.ExecuteReaderAsync(CommandListPosition commandListPosition, ICommandPayloadCreator payloadCreator, CommandBehavior behavior, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/Core/CommandExecutor.cs:line 56
   at MySqlConnector.MySqlCommand.ExecuteNonQueryAsync(IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlCommand.cs:line 309
   at MySqlConnector.MySqlCommand.ExecuteNonQuery() in /_/src/MySqlConnector/MySqlCommand.cs:line 108
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteNonQuery(RelationalCommandParameterObject parameterObject)
   at Microsoft.EntityFrameworkCore.Migrations.MigrationCommand.ExecuteNonQuery(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.ExecuteNonQuery(IEnumerable`1 migrationCommands, IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String connectionString, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabaseImpl(String targetMigration, String connectionString, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Invalid default value for 'Id'

I compared dotnet ef migrations script result for versions 8.0.0 and 8.0.2 of Pomelo.EntityFrameworkCore.MySql, and I see that for 8.0.0 there was two-step procedure. AUTO_INCREMENT was not set directly in the ALTER TABLE call, instead of this the POMELO_AFTER_ADD_PRIMARY_KEY procedure was used with some auto-detection logic for identity columns inside.

ALTER TABLE `Users` ADD `Id` int NOT NULL DEFAULT 0;

ALTER TABLE `Users` ADD CONSTRAINT `PK_Users` PRIMARY KEY (`Id`);
CALL POMELO_AFTER_ADD_PRIMARY_KEY(NULL, 'Users', 'Id');

And for 8.0.2, despite the POMELO_AFTER_ADD_PRIMARY_KEY procedure still exists in the migration script, it is not called. The column is created directly with DEFAULT 0 AUTO_INCREMENT combination of params, which cannot be accepted by MySQL Server for some reason.

ALTER TABLE `Users` ADD `Id` int NOT NULL DEFAULT 0 AUTO_INCREMENT,
ADD CONSTRAINT `PK_Users` PRIMARY KEY (`Id`);

Further technical details

MySQL version: 8.0.29 Operating system: Microsoft Windows 10 Pro Pomelo.EntityFrameworkCore.MySql version: 8.0.2 Microsoft.AspNetCore.App version:

atsidaev avatar Apr 25 '24 15:04 atsidaev