GithubHelp home page GithubHelp logo

Comments (4)

roji avatar roji commented on August 20, 2024

To be honest, I would have expected that defining a value converter for a given type would also convert (Postgres) arrays of that type.

You should indeed be defining a value converter on the element type of MyEnums, rather than a value converter for the entire array; once you do the latter, EF has no way of knowing what the actual internal representation is that's returned by your value converter, and so is unable to translate queries over it.

Try the following:

modelBuilder.Entity<MyModel>().PrimitiveCollection(b => b. MyEnums).ElementType().HasConversion(typeof(MyEnumValueConverter));

Let me know if that solves it for you. Unfortunately the EF docs are quite behind on these details...

from efcore.pg.

ffried avatar ffried commented on August 20, 2024

@roji Thanks for the quick reply!

Try the following:

modelBuilder.Entity<MyModel>().PrimitiveCollection(b => b.MyEnums).ElementType().HasConversion(typeof(MyEnumValueConverter));

Thanks for the hint here - I really haven't seen the PrimitiveCollection API anywhere yet.
Unfortunately, it still doesn't work and it still uses the enum case name in the query:

Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (15ms) [Parameters=[@__myEnum_0='Case2' (Nullable = false)], CommandType='Text', CommandTimeout='30']
      SELECT m.id, m.my_enum, m.my_enums
      FROM my_model AS m
      WHERE m.my_enums @> ARRAY[@__myEnum_0]::varchar(16)[]

Here's the db context code I'm now using:

ApplicationDbContext.cs

public sealed class ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : DbContext(options)
{
    public DbSet<MyModel> MyModels { get; init; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        base.OnConfiguring(optionsBuilder);
        var dataSource = new NpgsqlDataSourceBuilder("Host=127.0.0.1:5432;Database=test;Username=postgres;Password=MySecretPwd");
        optionsBuilder.UseNpgsql(dataSource.Build())
            .EnableDetailedErrors()
            .EnableSensitiveDataLogging();
    }

    private sealed class MyEnumValueConverter() : ValueConverter<MyEnum, string>(
        e => e.GetString(),
        s => s.GetMyEnum()
    );

    protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
    {
        base.ConfigureConventions(configurationBuilder);

        configurationBuilder.Properties<MyEnum>().HaveConversion<MyEnumValueConverter>();
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<MyModel>(entity =>
        {
            entity.Property(e => e.MyEnum)
                .HasConversion<MyEnumValueConverter>();
            entity.PrimitiveCollection(e => e.MyEnums)
                .ElementType()
                .HasConversion<MyEnumValueConverter>();

            entity.HasData(new MyModel
            {
                Id = 1,
                MyEnum = MyEnum.Case3,
                MyEnums = [MyEnum.Case1, MyEnum.Case2],
            });
        });
    }
}


Btw. is this primitive collection configuration also possible via conventions? In my original project we're configuring these enums via an attribute where we then configure the enums with that attribute in the ConfigureConventions method.

from efcore.pg.

snebjorn avatar snebjorn commented on August 20, 2024

I got this working using the PrimitiveCollection trick :)
EF support enums as strings. I got it working using

modelBuilder.Entity<MyModel>().PrimitiveCollection(b => b.MyEnums).ElementType().HasConversion<string>();

I tested this query and it worked!

_context.Foos.Where(x => x.MyEnums.Contains(MyEnum.Foo))

Thank you!

from efcore.pg.

ffried avatar ffried commented on August 20, 2024

It seems to work with the default EnumToStringConverter (which is what HasConversion<string>() uses according to the docs). But custom converters seem to be ignored at least partially. My HasData call seems to use it, but the query generated by the controller call doesn't.

from efcore.pg.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.