-
Notifications
You must be signed in to change notification settings - Fork 251
Open
Description
Description
When querying entities that include PostgreSQL enum properties, EF Core throws an InvalidCastException indicating that reading as System.Int32 is not supported for enum fields. This configuration worked correctly in Npgsql 8.x but is broken in Npgsql 10.0 RC.
Error Details
System.InvalidCastException: Reading as 'System.Int32' is not supported for fields having DataTypeName 'public.recipe_difficulty'
Source: Npgsql
Inner Exception:
NotSupportedException: Reading and writing unmapped enums requires an explicit opt-in; call 'EnableUnmappedTypes' on 'NpgsqlDataSourceBuilder' or NpgsqlConnection.GlobalTypeMapper
Stack Trace:
at Npgsql.Internal.AdoSerializerHelpers.<GetTypeInfoForReading>g__ThrowReadingNotSupported|0_0(Type type, PgSerializerOptions options, PgTypeId pgTypeId, Exception inner)
at Npgsql.Internal.AdoSerializerHelpers.GetTypeInfoForReading(Type type, PgTypeId pgTypeId, PgSerializerOptions options)
at Npgsql.BackendMessages.FieldDescription.<GetInfoCore>g__GetInfoSlow|51_0(Type type, ColumnInfo& lastColumnInfo)
at Npgsql.BackendMessages.FieldDescription.GetInfoCore(Type type, ColumnInfo& lastColumnInfo)
at Npgsql.BackendMessages.FieldDescription.GetInfo(Type type, ColumnInfo& lastColumnInfo)
at Npgsql.NpgsqlDataReader.<GetInfo>g__Slow|133_0(ColumnInfo& , PgConverter& , Size& , Boolean& , <>c__DisplayClass133_0& )
at Npgsql.NpgsqlDataReader.GetInfo(Int32 ordinal, Type type, PgConverter& converter, Size& bufferRequirement, Boolean& asObject)
at Npgsql.NpgsqlDataReader.GetFieldValueCore[T](Int32 ordinal)
at Npgsql.NpgsqlDataReader.GetInt32(Int32 ordinal)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.<MoveNextAsync>d__20.MoveNext()
Environment
- .NET Version: 10.0 (RC)
- Npgsql: 10.0.0-rc.1
- Npgsql.EntityFrameworkCore.PostgreSQL: 10.0.0-rc.2
- Entity Framework Core: 10.0.0-rc.2.25502.107
- PostgreSQL: 15.3 (Debian 15.3-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
- Operating System: Windows 10
Configuration
Enum Definition
public enum RecipeDifficulty
{
Easy = 0,
Medium = 1,
Hard = 2
}PostgreSQL Enum Type
CREATE TYPE recipe_difficulty AS ENUM ('Easy', 'Medium', 'Hard');DbContext Configuration
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Register enum types
modelBuilder.HasPostgresEnum<RecipeDifficulty>(schema: "public", name: "recipe_difficulty");
// Configure entity property
modelBuilder.Entity<Recipe>(entity =>
{
entity.Property(e => e.Difficulty)
.HasColumnType("public.recipe_difficulty");
});
}Service Registration
// Register NpgsqlDataSource with enum mappings
builder.Services.AddSingleton(provider =>
{
IConfiguration configuration = provider.GetRequiredService<IConfiguration>();
string connectionString = configuration["POSTGRESQL:CONNECTIONSTRING"]!;
NpgsqlDataSourceBuilder dataSourceBuilder = new(connectionString);
dataSourceBuilder.MapEnum<RecipeDifficulty>(
"recipe_difficulty",
new NpgsqlNullNameTranslator());
return dataSourceBuilder.Build();
});
// Register DbContext using the NpgsqlDataSource
builder.Services.AddDbContext<MyDbContext>((serviceProvider, options) =>
{
NpgsqlDataSource dataSource = serviceProvider.GetRequiredService<NpgsqlDataSource>();
options.UseNpgsql(dataSource, b => b.MigrationsAssembly("MyMigrationsAssembly"));
});Model Snapshot
The enum is properly registered in the model snapshot:
NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "public", "recipe_difficulty", new[] { "Easy", "Medium", "Hard" });
// Property configuration
b.Property<RecipeDifficulty>("Difficulty")
.HasColumnType("public.recipe_difficulty")
.HasColumnName("difficulty");Expected Behavior
EF Core should successfully read enum values from PostgreSQL enum columns and map them to the corresponding C# enum type.
Actual Behavior
EF Core attempts to read the enum as Int32, causing an InvalidCastException. The error message suggests calling EnableUnmappedTypes(), but this should not be necessary when enums are explicitly mapped via MapEnum().
Worked in Previous Version
This exact configuration worked correctly in:
- Npgsql: 8.x
- Npgsql.EntityFrameworkCore.PostgreSQL: 8.x
Attempted Solutions
- Added
EnableUnmappedTypes()toNpgsqlDataSourceBuilder- Error persists - Added EF-level
MapEnum()inUseNpgsqloptions builder - Error persists - Verified enum registration in
OnModelCreating- Already present - Verified property configuration in model snapshot - Already present
- Verified
HasColumnType("public.recipe_difficulty")on property - Already present
Additional Context
- The enum is properly mapped in
NpgsqlDataSourceBuilderwith appropriate name translators - The enum is registered in EF Core's model via
HasPostgresEnum - The property is correctly configured with
HasColumnType - The model snapshot includes the enum registration and property configuration
- The error occurs when EF Core tries to materialize query results, not during query construction
Questions
- Is
EnableUnmappedTypes()required even when enums are explicitly mapped viaMapEnum()in Npgsql 10.0 RC? - When using an external
NpgsqlDataSource, are there additional configuration steps required that differ from Npgsql 8.x? - Is there a breaking change in enum handling between Npgsql 8.x and 10.0 RC that requires different configuration?
Reproduction Steps
- Create a PostgreSQL enum type
- Create a C# enum matching the PostgreSQL enum
- Configure
NpgsqlDataSourcewithMapEnum<T>() - Register enum in EF Core with
HasPostgresEnum<T>() - Configure entity property with
HasColumnType("public.enum_name") - Query entities that include the enum property
- Exception occurs when EF Core tries to materialize results
Metadata
Metadata
Assignees
Labels
No labels