-
Notifications
You must be signed in to change notification settings - Fork 227
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
Enum mapping with v9 and ordering #3390
Comments
@bmarkovic17 thanks for reporting.. It looks like the new automatic support in EF 9 (which obviates HasPostgresEnum) is simply configuring the enums in a different order, nothing more. That means that you should be able to generate a new migration with 9.0, and then empty the migration of all contents - so have an empty Up/Down migration - since no actual database change needs to happen (enum label ordering is irrelevant. This will ensure that your context snapshot is now aligned with what EF 9 generates, and from that point on everything should be OK. In other words, this seems like a one-time wrinkle in the transition from the pre-9 explicit HasPostgresEnum() to the new 9 support. I'll go ahead and close this for now as I don't see what can be done to avoid it, and on the other hand it's very easy to work around. But please post back here to let me know how it goes, and I'll reopen if needed. |
Thanks @roji for the quick reply. I can confirm that with an empty migration I could remove the |
Great, thanks for confirming! Though if you're on 9 and aer using the new ConfigureDataSource(), you should only need to be mapping your enums in a single place (docs). |
Sorry for my late reply and thanks for the heads up on this, I don't know how we missed this. We got rid of the external Thanks again for all the help and quick replys. |
Hello! After migrating to It's not a problem for us, but we'll have to keep a "close watch" on each migration and change manually ) |
@or2e that definitely shouldn't happen - try taking a look at the context snapshot (that's the file next to the migration which captures the model as it is after the migration). If you can put together some sort of minimal repro for this, please open a new issue and I'll investigate. |
Can I ask a question? I suspect that this is why the order changes in subsequent migrations, because I didn't commit it in the snapshot. |
You are not supposed to modify those files yourself - EF generates them when you add a new migration (and they're supposed to contain up-to-date info about your model, including the correct enum ordering). However, you do have to commit them. |
We just got hit by this issue too.
I think this works indeed
But this seems wrong. In PostgreSQL, enums are ordered and you can compare enum values to each other. We currently don't do that in our code, but we must be careful not to do it in the future as it won't behave as expected. |
Columns in a table also have an ordering (the order in which they were created), but that shouldn't be relevant to you when using EF in any way. |
I agree for columns, but it's not the same for enums since EF allows you to write something like myTable.Where(o => o.MyEnum > Enum.SomeValue); And the meaning of this line changes depending on the order of the enum. |
Yes, .NET allows you to order by enums; but this will not necessarily have the same meaning when doing it in .NET (the ordering is based on the underlying int value, which itself is based on declaration order in the .NET enum) and in SQL (PostgreSQL enums aren't numbers). It's true that we could (by default) create enum labels in the order in which they were defined in .NET, making the two consistent; this would allow PG enums to e.g. sort in the same way as their .NET counterparts. But PG is limited in terms of altering existing enums (e.g. reordering/removing existing labels isn't supported). In any case, I've opened #3398 to track this. In any case, any user who really cares about label ordering can use HasPostgresEnum as before and manually specify the exist ordering they want. The only thing that changed is that version 9 of the provider effectively does HasPostgresEnum implicitly for you, in alphabetical order. |
@roji public enum SessionStatus
{
Created = 1,
InProgress = 2,
Completed = 3,
Failed = 4
} ModelSnapshot: NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "SessionStatus", new[] { "Created", "InProgress", "Completed", "Failed" }); After upgrading to EF 9 I create a new migration and in that migration I have changes for the enums: migrationBuilder.AlterDatabase()
.Annotation("Npgsql:Enum:SessionStatus", "Completed,Created,Failed,InProgress")
.OldAnnotation("Npgsql:Enum:SessionStatus", "Created,InProgress,Completed,Failed"); And ModelSnapshot: NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "SessionStatus", new[] { "Completed", "Created", "Failed", "InProgress" }); A SQL script is executed while the database is being updated: ALTER TYPE "SessionStatus" ADD VALUE 'Completed' BEFORE 'Created'; and there's an exception:
|
@ValeriyGourov thanks for flagging this - I can see it happening. I opened #3424 to track this separately, as this issues already discusses various other, unrelated aspects of this. |
Hello,
I have a question about the new enum mapping with which we are having some issues while doing our migration from v8 to v9. We are migrating a project that has 3 enums mapped I would say in the standard way:
NpgsqlDataSource
we usedMapEnum<T>
to map each enumOnModelCreating
method we usedHasPostgresEnum<T>
to register each of the enumsAfter updating the nuget packages and
dotnet-ef
tool, we created a new migration that wanted to revert our enum based table columns back to integers. We saw in the documentation that enum mapping is changing considerably with v9, so we removed invocations of theHasPostgresEnum<T>
from ourOnModelCreating
method and addedMapEnum<T>
calls toUseNpgsql
'snpgsqlOptionAction
delegate (both on ourIDesignTimeDbContextFactory
implementation andAddDbContextFactory<T>
'soptionsAction
). Unfortunately, that didn't work out as the migration created with this configuration resulted in recreating the same DB enums but with different sort order (the order before was the same as in our C# enum, but with v9 it is alphabetically)After further analysis and troubleshooting we noticed that if we also add back the
HasPostgresEnum<T>
part to ourOnModelCreating
method we get it to work as it was, i.e. new migrations aren't changing anything about our existing mapped enums. I'm not sure if we are doing something wrong or this is supposed to work like this, but with v9 we now have to keep our enum mappings in 4 places, while before we had to keep it in 2, which was also not ideal.Thanks.
The text was updated successfully, but these errors were encountered: