-
Notifications
You must be signed in to change notification settings - Fork 223
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
Data source enum mapping doesn't work #2557
Comments
Something made me try and run a migration. Nothing has changed up to this point. Running
public partial class Test : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<int>(
name: "type",
table: "auth_system_roles",
type: "integer",
nullable: false,
defaultValueSql: "'normal'",
oldClrType: typeof(int),
oldType: "auth_role_type",
oldDefaultValueSql: "'normal'");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<int>(
name: "type",
table: "auth_system_roles",
type: "auth_role_type",
nullable: false,
defaultValueSql: "'normal'",
oldClrType: typeof(int),
oldType: "integer",
oldDefaultValueSql: "'normal'");
}
} Notice that the I realized that we are using a design-time factory and that was still using a connection string. I converted that over to Data source builder and mapped the Enum there as well (should this be needed in this case?). This didn't change anything and I still get the same migration. If I explicitly set the column type entity.Property(e => e.Type)
.HasDefaultValueSql("'normal'")
.HasColumnName("type")
.HasColumnType("auth_role_type") // add this, no more migration
.IsRequired(); [ This is probably a red herring but shouldn't the column type be inferred properly without anything special as before? We use a library for snake-casing-ifying tables/columns/types etc. and I'd prefer not to be specifying the type name directly ] |
Something else I discovered... I created a new blank database trying to determine if there was something corrupt about my current one (there isn't). But in the process I started with some blank data sets. If I run the queries above against the tables without any data in them they return just fine (but empty, of course). If I try adding a record to the database, I get weird behavior. For example this will throw an exception--but it will add the value to the underlying database: _database.AuthSystemRoles.Add(new AuthSystemRole { AuthRoleName = "x", Type = AuthRoleType.Normal });
await _database.SaveChangesAsync(); And the thrown exception:
|
Also note that the exception messages from the OP are based on my actual context class which has a lot more to it (more types, snake case naming plugin, etc). I have reproduced this with a new context, exactly as it appears in the OP (which I've modified slightly to be standalone). The exceptions are mostly the same, the overall problem persisting. Everything works fine if I use the global type mapper (along with the data source). |
I'm having the same problem. EF7 seems to ignore enum mappings created in Using |
I have the same problem. When using dbDataSource to map enum the migration would use int as the field's default type. While when using NpgsqlConnection.GlobalTypeMapper to map enum it would use the specific type but it is obsolete. By the way, can we add more description in the ef core part of the document? I was really confused about how to use dataSource to map enum in a asp.net project until I found examples in the issue #2603. And ef core part of the document does not mention that NpgsqlConnection.GlobalTypeMapper is obsolete. |
Pushed a fix for this, the next patch version will contain it. It would be great if people can test with the daily build an confirm, just in case there are any outstanding issues. To do that, simply grab the latest v7.0.2 daily build (7.0.2-ci.20230129T151307 or above) from the release feed. |
I tested it and it works fine. However, issue #2603 still exists. The generated migrations still use int as the type of the enum fields as the following figure shows(line 101). I am not sure if it will affect some other things since the generated migrations work and it can map enum correctly. |
I am unable to test until tomorrow morning at the earliest. I also had the migration issue with the integer type, so I can double check that as well. I'll report back. Can I ask what the fix is/was? I tried to follow the PR/commit but I'm a bit confused. Correct me if I'm wrong, but It looks like you're delegating back to the |
@HHaoWang I'm unable to reproduce this - when I generate the migration (using the new patched version), I can see the generation migration code defining |
GlobalTypeMapper is still being accessed since we still want it to work, i.e. not break backwards compat for people still using global type mapping. But this code fragment now also gets enum mappings out of the configured data source. |
I can confirm that the latest daily fixes the issues. Thanks! |
I'm not sure if I've chosen the correct topic. but it looks like a similar issue. When enum mapped to db type with non-default schema, enum type is created correctly, but columns mapped to type with default scheme. /// <inheritdoc />
public partial class Initial : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.EnsureSchema(
name: "enum_schema");
migrationBuilder.AlterDatabase()
.Annotation("Npgsql:Enum:test_enum", "first,second,third")
.Annotation("Npgsql:Enum:test_enum2", "n1,n2,n3");
migrationBuilder.CreateTable(
name: "TestEntities",
schema: "enum-schema",
columns: table => new
{
Id = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
Name = table.Column<string>(type: "text", nullable: false),
Enum = table.Column<TestEnum>(type: "test_enum", nullable: false),
Enum2 = table.Column<TestEnum2>(type: "test_enum2", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_TestEntities", x => x.Id);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "TestEntities",
schema: "enum-schema");
}
} Although the annotation creation command does not contain the schema, it is implicitly applied for an enum type, but not for a column type that has that type. CREATE TABLE IF NOT EXISTS "__EFMigrationsHistory" (
"MigrationId" character varying(150) NOT NULL,
"ProductVersion" character varying(32) NOT NULL,
CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY ("MigrationId")
);
START TRANSACTION;
DO $EF$
BEGIN
IF NOT EXISTS(SELECT 1 FROM pg_namespace WHERE nspname = 'enum_schema') THEN
CREATE SCHEMA enum_schema;
END IF;
END $EF$;
DO $EF$
BEGIN
IF NOT EXISTS(SELECT 1 FROM pg_namespace WHERE nspname = 'enum_schema') THEN
CREATE SCHEMA enum_schema;
END IF;
END $EF$;
CREATE TYPE enum_schema.test_enum AS ENUM ('first', 'second', 'third');
DO $EF$
BEGIN
IF NOT EXISTS(SELECT 1 FROM pg_namespace WHERE nspname = 'enum_schema') THEN
CREATE SCHEMA enum_schema;
END IF;
END $EF$;
CREATE TYPE enum_schema.test_enum2 AS ENUM ('n1', 'n2', 'n3');
CREATE TABLE enum_schema."TestEntities" (
"Id" numeric(20,0) NOT NULL,
"Name" text NOT NULL,
"Enum" test_enum NOT NULL,
"Enum2" test_enum2 NOT NULL,
CONSTRAINT "PK_TestEntities" PRIMARY KEY ("Id")
);
INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
VALUES ('20231119201535_Initial', '7.0.13');
COMMIT; Also, ensure schema is triggered 3 times - every HasPostgresEnum adds to migration script schema creation command even if the type's schema equals to a default database schema. |
@iPilot please open a new issue (this one was resolved), including a fully runnable, minimal repro. The actual C# code containing your model configuration and setup is missing. |
I don't know if this is an issue here or in Npgsql.
I am using
Npgsql.EntityFrameworkCore.PostgreSQL
version7.0.0
onnet7.0
. I am trying to use the newDbDataSource
overload ofUseNpgsql
along with a mapped Postgres Enum. The following:and then this query:
Throws the following exception:
I also get a different error when trying to project to a dictionary:
I found this line interesting:
However if I continue to use the Global Type mapper, everything works fine:
If it matters I am running on Postgres 11.
Edit: added explicit column names (my actual context uses a plugin for snake case naming which I've removed in my local repro as well)
The text was updated successfully, but these errors were encountered: