Search code examples
c#enumsentity-framework-corenpgsqlef-core-3.1

Npgsql enum array with int conversion throws InvalidCastException on "Contains"


I'm using an enum to int conversion for enum arrays in npgsql due to lack of enum altering features.

Model:

public class TestEntity
{
    public Guid Id { get; set; }
    public TestEnum[] Enums { get; set; }

    public TestEntity()
    {
        Enums = new TestEnum[0];
    }
}

public enum TestEnum
{
    NONE,
    FIRST,
    SECOND,
    THIRD
}

Context:

public class TestContext : DbContext
{
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<TestEntity>()
            .Property(x => x.Enums)
            .HasConversion(
                e => e.Cast<int>().ToArray(),
                e => e.Cast<TestEnum>().ToArray());
    }
}

When I'm reading or writing entities from/to DB without "touching" array properties in LINQ expressions everything works perfectly - columns are of type integer[] in Postgres and mapping works as should.

However, when I'm using "Contains" function on enum[] property, it throws with InvalidCastException: "Can't write CLR type Proj.TestEnum with handler type Int32Handler".

Example:

var param = TestEnum.FIRST; 
            
var result = context.TestEntities!
    .Where(x => x.Enums.Contains(param))
    .ToArray();

Is there something I'm missing?


Solution

  • This is kind of a case of this issue: using value converters blocks method translation.

    This should work fine if using the Npgsql's native enum support, rather than doing value conversions. You say you don't want to do that because of the lack of enum altering features - can you be more specific? PostgreSQL does support adding and renaming enum values, and you can do that via raw SQL in your migrations.