Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unsafe use of new value "x" of enum type y when running multiple migrations at the same time #3389

Closed
GaetanK4 opened this issue Nov 27, 2024 · 2 comments

Comments

@GaetanK4
Copy link

Hello,
When upgrading to .NET 9, I have this error unsafe use of new value "entity3" of enum type entity_type when adding a new value to an existing enum in a first migration, using this value in a second migration and running both of these migrations at the same time. This error occurs when using await dbContext.Database.MigrateAsync(); or dotnet ef database update.

Before upgrading (in .NET 8) I had this error only when I was using the new added value in the same migration as its addition.

Here's a minimal code and steps to replicate the error :

  • Create an initial migration with Entity3 still commented in EntityType enum
  • Uncomment Entity3 and create another migration
  • Create a third empty migration and add this code in the Up() : migrationBuilder.Sql("INSERT INTO entity (id, type) VALUES (uuid_generate_v4(), 'entity3')");
  • Run the app or use dotnet ef database update
using Microsoft.EntityFrameworkCore;
using Npgsql;

var builder = WebApplication.CreateBuilder(args);

NpgsqlDataSourceBuilder dataSourceBuilder = new("Server=localhost; Port=5432; Database=sandbox; Userid=postgres; Password=admin;");
dataSourceBuilder.MapEnum<EntityType>();
var dataSource = dataSourceBuilder.Build();

// .NET 9
builder.Services.AddDbContext<AppDbContext>(options => { options.UseNpgsql(dataSource, opts => opts.MapEnum<EntityType>()); });

// .NET 8
//builder.Services.AddDbContext<AppDbContext>(options => { options.UseNpgsql(dataSource); });

var app = builder.Build();

await using var scope = app.Services.CreateAsyncScope();
await using var dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
await dbContext.Database.MigrateAsync();

await app.RunAsync();

public class AppDbContext : DbContext
{
	public AppDbContext()
	{
	}

	public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
	{
	}

	protected override void OnModelCreating(ModelBuilder modelBuilder)
	{
		modelBuilder.HasPostgresExtension("uuid-ossp");

		// .NET 8
		//modelBuilder.HasPostgresEnum<EntityType>();

		var entityBuilder = modelBuilder.Entity<Entity>();
		entityBuilder.ToTable("entity");
		entityBuilder.HasKey(x => x.Id);
		entityBuilder.Property(x => x.Id).HasColumnName("id");
		entityBuilder.Property(x => x.Type).HasColumnName("type");
	}
}

public class Entity
{
	public Guid Id { get; set; }
	public EntityType Type { get; set; }
}

public enum EntityType
{
	Entity1,
	Entity2

	// Uncomment before adding the second migration
	//Entity3
}

There is no error when updating the database first to the second migration and then to the third so to me it seems like a missing commit; or something like that between migrations in the same run.

And I'm not sure that this is relevant to this issue but when using await dbContext.Database.MigrateAsync(); to create the database at the first run of the app (which I know is not a good practice but I need to use it in my integration tests) there is this error An error occurred using the connection to database 'sandbox' on server 'tcp://localhost:5432'. but it's still create and migrate the database. You can see this error in the console when running the app with the above steps. And this error was not present in the previous versions.

@roji
Copy link
Member

roji commented Nov 28, 2024

Yeah, this is the result of an EF9 change, where all migrations are now executed within a single transaction, and PostgreSQL doesn't support adding an enum value and using it in the same transaction; this has been flagged here: dotnet/efcore#35096 (comment). We'll be discussing what to do on this kind of issue on the EF side, in the meantime you can suppress the transaction, or simply apply the migrations in two steps (first go up to the migration that adds the enum, then the rest).

@roji roji closed this as not planned Won't fix, can't repro, duplicate, stale Nov 28, 2024
@GaetanK4
Copy link
Author

Thanks for the clarification and the work around.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants