我想在我的模型中使用一个枚举,但在数据库中它被存储为Description属性值,我如何才能让EF核心理解这一点?

public enum ItemType
{
    [Description("s")]
    Floor,
    
    [Description("i")]
    Wall
}

型号:

public class Item
{
    public int Id { get; set; }
    public ItemType Type { get; set; }
}

映射

modelBuilder.Entity<ItemDto>()
    .Property(e => e.Type)
    .HasConversion<string>();

推荐答案

正如 comments 中所讨论的,EF Core不知道如何根据DescriptionAttribute转换/映射Enum值.您需要实现一个Value Converter来执行映射.

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

ValueConverter中的第一个参数是将Enum值转换为基于DescriptionAttribute的字符串(从模型到数据库).

ValueConverter中的第二个参数是将存储的DB(字符串)值转换为Enum(从DB到模型).

同时,我实现了在您的场景中所必需的extension/helper方法.

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

Csharp相关问答推荐

无法更改或使用C#(WinForms.NET)中的全局变量

为什么.Equals(SS,StringComparison. ClientCultureIgnoreCase)在Net 4.8和6.0之间不同?

PredicateBuilder不是循环工作,而是手动工作

Regex在c#中完全匹配

如何循环遍历XML文档 node 以使用XSLT存储值

当我使用NET6作为目标框架时,为什么DotNet使用NET8作为MS包?

如何在C#中将对象[*,*]直接转换为字符串[*,*]?

与C#中的Zip列表并行

使用C#HttpClient以多部分形式数据发送带有非ASCII文件名的文件的问题

单元测试:模拟返回空

在swagger示例中添加默认数组列表

如果设置了另一个属性,则Newtonsoft JSON忽略属性

ASP.NET Core MVC将值从视图传递到控制器时出现问题

委托RequestDelegate不带2个参数-ASP.NET Core 8最小API

.Net MAUI,在将FlyoutPage添加到容器之前,必须设置添加构造函数导致Flyout和Detail"

这是否比决定是否使用ConfigureAWait(False)更好?

类/值和日期的泛型方法

RCL在毛伊岛应用程序和Blazor服务器应用程序.Net 8.0中使用页面

Foreach非常慢的C#

删除MudRadio时,MudRadioGroup未 Select 正确的MudRadio