GithubHelp home page GithubHelp logo

Support PostgreSQL enums about efcore.pg HOT 18 CLOSED

npgsql avatar npgsql commented on May 22, 2024
Support PostgreSQL enums

from efcore.pg.

Comments (18)

roji avatar roji commented on May 22, 2024 6

@myrup I'm actively working on this, it involves many things across the stack. I'm really hoping it'll make it into preview2.

from efcore.pg.

roji avatar roji commented on May 22, 2024 6

This has been merged and will be released with 2.1.0-preview2.

For now, the depends on Npgsql 4.0.0, which is still in development - not ideal. We'll see how the release cycles of EF Core and Npgsql coincide and see what to do.

from efcore.pg.

roji avatar roji commented on May 22, 2024 5

@ajcvickers, @divega and everyone else interested in this, I've completed a hacky prototype that successfully maps to PostgreSQL native enums. Enum types can even be defined using a fluent API on the model and are created as part of migrations. I will probably complete support for this, including scaffolding, for 2.1.

It's really, really nice to be able to do all this with EF Core, great going guys!

from efcore.pg.

roji avatar roji commented on May 22, 2024 4

@julielerman you're not going to be able to map to a PG enum because of limitations in EFCore, this is what this issue is about. My hope is that when EFCore does support native database enums you'll be able to have the same model mapping to enum on PostgreSQL and to int on sqlite.

from efcore.pg.

ian-luca avatar ian-luca commented on May 22, 2024 3

@roji Any news on when this feature will be implemented or how this issue can be bypassed?

from efcore.pg.

ajcvickers avatar ajcvickers commented on May 22, 2024 3

@roji Very cool! I have a PR out for the enum literal bug.

from efcore.pg.

divega avatar divega commented on May 22, 2024 2

@roji Thanks for the update. That sounds really cool! It is also great because you are helping us validate (and improve 😄) the type mapping design.

from efcore.pg.

roji avatar roji commented on May 22, 2024

It seems the EF7 doesn't support database enum mapping right now, mapping enums to numeric types instead. Have opened dotnet/efcore#3620 for this.

from efcore.pg.

vankooch avatar vankooch commented on May 22, 2024

Hi is there a workaround until this get fixed?

from efcore.pg.

roji avatar roji commented on May 22, 2024

I think you should be able to have enums on your entities, it's just that they'll be mapped to database int columns instead of PostgreSQL enums. I haven't confirmed this yet, though.

from efcore.pg.

julielerman avatar julielerman commented on May 22, 2024

Yes, I'm using enums and getting integers by default. I haven't tried mapping to a posgres enum type but I do need to flip to sqlite occasionally so leaving it as int.

from efcore.pg.

julielerman avatar julielerman commented on May 22, 2024

thanks. I realize now that enum isn't just a type to specify with HasColumnType so understand why even though basic enum support is now working in EFCore, that this is a much farther stretch.

from efcore.pg.

vankooch avatar vankooch commented on May 22, 2024

@roji I can confirm that using a enum in C# and mapping it to an int in the database does work.

My problem is that we do already use enums as custom types in postgres. So I was looking for a solution for that case. Anyway I've a working solution it's not the best but it works. It does require that the enum in C# has the PgName attributes set.

Change the model like this:

[NotMapped]
public MyEnum Type
{
    get
    {
        return GetEnumValueByPgName(MyEnum.Value1, this.TypeDatabase);
    }

    set
    {
        this.TypeDatabase = value.GetPgName();
    }
}

[Column("type")]
public string TypeDatabase { get; protected set; }

This is the helper function I use:

/// <summary>
/// Gets PgName value for enum
/// </summary>
/// <param name="enumVal">The enum value</param>
/// <returns>PgName or empty if not found</returns>
public static string GetPgName(this Enum enumVal)
{
    var type = enumVal.GetType();
    var memInfo = type.GetMember(enumVal.ToString());
    if (memInfo.Count() == 0)
    {
        return null;
    }

    var attributes = memInfo[0].GetCustomAttributes(typeof(NpgsqlTypes.PgNameAttribute), false).ToArray();
    if (attributes?.Length > 0)
    {
        var name = (NpgsqlTypes.PgNameAttribute)attributes[0];
        if (name != null)
        {
            return name.PgName;
        }
    }

    return string.Empty;
}

/// <summary>
/// Get enum value by PgName. Use as workaround for bug in EfCore.
/// </summary>
/// <param name="defaultValue">Default value to set if could not find a match</param>
/// <param name="pgname">PgName used in database</param>
/// <returns>Mapped value or default value</returns>
public static TEnum GetEnumValueByPgName<TEnum>(this TEnum defaultValue, string pgname)
{
    if (string.IsNullOrEmpty(pgname))
    {
        return defaultValue;
    }

    var type = typeof(TEnum).GetTypeInfo();
    if (!type.IsEnum)
    {
        throw new TypeLoadException("Given type is not an enum.");
    }

    foreach (var item in type.GetMembers())
    {
        var attributes = item.GetCustomAttributes(typeof(NpgsqlTypes.PgNameAttribute), false).ToArray();

        if (attributes?.Length > 0)
        {
            var name = (NpgsqlTypes.PgNameAttribute)attributes[0];
            if (name != null && name.PgName == pgname)
            {
                return (TEnum)Enum.Parse(typeof(TEnum), item.Name);
            }
        }
    }

    return defaultValue;
}

from efcore.pg.

roji avatar roji commented on May 22, 2024

@vankooch I'm surprised this actually works, but if it does why not.

from efcore.pg.

edjacob25 avatar edjacob25 commented on May 22, 2024

@vankooch Hey, your solution only works for retrieving right? I tried to use but I still get the Npgsql.PostgresException: 42804: column "payment_type" is of type payment_type but expression is of type text by at insertion time.

from efcore.pg.

roji avatar roji commented on May 22, 2024

@CoffeeDreamLabs there is a slight chance that this will be possible in the upcoming 2.1 release, but it doesn't depend on me or on Npgsql, but rather on EF Core itself. Go to dotnet/efcore#3620 and express your interest there.

from efcore.pg.

roji avatar roji commented on May 22, 2024

@ajcvickers will wait for that to be fixed (dotnet/efcore#11041), there's more than enough to do in the meantime...

from efcore.pg.

myrup avatar myrup commented on May 22, 2024

@roji dotnet/efcore#11041 was merged. Is there any way to start using your fix today?

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.