Home > Mobile >  Map enum EnumMember's value to column in Entity Framework
Map enum EnumMember's value to column in Entity Framework

Time:04-19

I have an enum with named fields using EnumMember. I want to be able to map these properties to Entity Framework.

public enum FormBasis
{
    [EnumMember(Value = "Order Based")]
    Order = 1,
    [EnumMember(Value = "Patient Based")]
    Patient = 2,
    [EnumMember(Value = "HCP Based")]
    HCP = 3
}

My entity looks like this

[Table("FormBasis")]
[Index(nameof(Name), IsUnique = true)]
public class FormBasisDto : EntityBase
{
    [Column("Name", TypeName = "varchar(50)")]
    public CM.FormBasis Name { get; set; }

    public virtual List<FormDto> Forms { get; set; }
}

I've tried

modelBuilder.Entity<FormBasisDto>()
    .Property(formBasis => formBasis.Name)
    .HasConversion(fb => fb.ToString(),
        fb => (CM.FormBasis)Enum.Parse(typeof(CM.FormBasis), fb));

I saved a record to my table where Name is set to Order Based. The error I get says Requested value 'Order Based' was not found.

Is there a more specific way of mapping the enum member value?

CodePudding user response:

You can use StringEnumConverter to convert Enum values to string:

    [Column("Name"), TypeName = "varchar(50)"]
    [Newtonsoft.Json.JsonConverter(typeof(StringEnumConverter))]
    public CM.FormBasis Name { get; set; }

If you need custom values for enum members, you can implement your own custom converter:

public class CustomJsonConverter : JsonConverter< FormBasis>
{
    public override FormBasis? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        //deserialize JSON into a FormBasis?
        return FormBasisEnumHelper.Parse(reader.GetString());
    }

    public override void Write(Utf8JsonWriter writer, FormBasis? value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToEnumString());
    }
}

CodePudding user response:

So I found a couple of converter methods a few posters put on here. I combined this approach and registered my enum conversion as follows.

public static class JsonHelper
{
    public static string GetEnumMemberValue<T>(this T value)
        where T : struct, IConvertible
    {
        return typeof(T)
            .GetTypeInfo()
            .DeclaredMembers
            .SingleOrDefault(x => x.Name == value.ToString())
            ?.GetCustomAttribute<EnumMemberAttribute>(false)
            ?.Value;
    }

    public static T ToEnum<T>(this string str)
        where T : Enum
    {
        var enumType = typeof(T);
        foreach (var name in Enum.GetNames(enumType))
        {
            var enumMemberAttribute = ((EnumMemberAttribute[])enumType.GetField(name).GetCustomAttributes(typeof(EnumMemberAttribute), true)).Single();
            if (enumMemberAttribute.Value == str) return (T)Enum.Parse(enumType, name);
        }
            
        return default;
    }
}

The registry in my OnModelCreating looks like this

modelBuilder.Entity<FormBasisDto>()
    .Property(formBasis => formBasis.Name)
    .HasConversion(fb => 
        fb.GetEnumMemberValue(),
        fb => fb.ToEnum<CM.FormBasis>());
  • Related