Skip to content

Support HasConversion to primitive collection types #33688

@PascalArdex

Description

@PascalArdex

Description

In the Entities we use Enum types a lot and we make sure to store them as strings instead of numbers
For this we use .HasConversion<string>(); and it works great.

Now we would like to also support collections of Enums and have them serialized as text[] for consistency
And you would think this is a job for EF Core 8 Primitive Collections and we are going to be able to simply use .HasConversion<string[]>(); but no luck.

Example

Entity

public class Rider
{
    public Guid Id { get; set; }
    public List<EquineBeast> Mounts { get; set; }
}

public enum EquineBeast
{
    Donkey,
    Mule,
    Horse,
    Unicorn
}

I will include the full code because we configure all Enum based entities at once

OnModelCreating

    private void SaveEnumAsString(ModelBuilder modelBuilder)
    {
        var entityTypes = modelBuilder.Model.GetEntityTypes();

        foreach (var entityType in entityTypes)
        {
            var enumProperties = entityType.ClrType.GetProperties()
                .Where(p => p.PropertyType.IsEnum
                    || (p.PropertyType.IsGenericType
                        && p.PropertyType.GetGenericTypeDefinition() == typeof(List<>)
                        && p.PropertyType.GetGenericArguments()[0].IsEnum));

            foreach (var enumProperty in enumProperties)
            {
                if(enumProperty.PropertyType.IsEnum)
                {
                    modelBuilder
                        .Entity(entityType.ClrType)
                        .Property(enumProperty.Name)
                        .HasConversion<string>();
                }
                else
                {
                    modelBuilder
                        .Entity(entityType.ClrType)
                        .Property(enumProperty.Name)
                        .HasConversion<string[]>();
                }
            }
        }
    }

Problem

Now here is the odd part.
When we create the migration EF Core is stuck with int[]

            migrationBuilder.CreateTable(
                name: "riders",
                columns: table => new
                {
                    id = table.Column<Guid>(type: "uuid", nullable: false),
                    mount = table.Column<int[]>(type: "integer[]", nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("pk_riders", x => x.id);
                });

We can force the column type with .HasColumnType("text[]") but it is creating more problems down the path.
Namely the migration will apply but at runtime fails to load/convert the field

Exception has occurred: CLR/System.InvalidCastException
Exception thrown: 'System.InvalidCastException' in Microsoft.EntityFrameworkCore.Relational.dll: 'Reading as 'System.Int32[]' is not supported for fields having DataTypeName 'text[]''

Version information

EF Core version: Microsoft.EntityFrameworkCore.Design 8.0.0
Database provider: Npgsql.EntityFrameworkCore.PostgreSQL 8.0.0
Target framework: net8.0

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions