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>());