I want to use an enum in my model, but in the database its stored as the Description
attribute value, how can I make EF core understand this?
public enum ItemType
{
[Description("s")]
Floor,
[Description("i")]
Wall
}
Model:
public class Item
{
public int Id { get; set; }
public ItemType Type { get; set; }
}
Mapping
modelBuilder.Entity<ItemDto>()
.Property(e => e.Type)
.HasConversion<string>();
As discussed in the comment, EF Core doesn't know how to convert/mapping the Enum value based on the DescriptionAttribute
. You need to implement a Value Converter to perform the mapping.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var enumDescriptionMappingConverter = new ValueConverter<ItemType, string>(
v => v.ToDescription(),
v => EnumExtensions.GetValueByDescriptionAttribute<ItemType>(v));
modelBuilder.Entity<Model>()
.Property(e => e.Type)
.HasConversion(enumDescriptionMappingConverter);
}
The first argument in ValueConverter
is which converts the Enum
value to a string based on DescriptionAttribute
(From model to DB).
The second argument in ValueConverter
is which converts the stored DB (string) value to the Enum
(From DB to model).
While, I implement the extension/helper methods that are necessary in your scenario.
public static class EnumExtensions
{
public static string ToDescription(this Enum value)
{
var attribute = value.GetAttribute<DescriptionAttribute>();
if (attribute == null)
return value.ToString();
return attribute.Description;
}
public static TEnum GetValueByDescriptionAttribute<TEnum>(string value)
where TEnum : Enum
{
var enumDict = Enum.GetValues(typeof(TEnum))
.Cast<TEnum>()
.ToDictionary(k => k, v => v.ToDescription());
return enumDict
.Single(x => x.Value == value)
.Key;
}
private static T GetAttribute<T>(this Enum value)
where T : Attribute
{
Type type = value.GetType();
MemberInfo[] memberInfo = type.GetMember(value.ToString());
var attributes = memberInfo[0].GetCustomAttributes(typeof(T), false);
return (T)attributes.FirstOrDefault();
}
}