关于c#:如何将数据库中的枚举保存为字符串

How to save enum in database as string

这是我的模型类,我们有一个可能是僵尸或人类的类型

1
2
3
4
5
6
7
8
9
10
11
12
public class User
{
    public int ID { get; set; }
    public string Name { get; set; }
    public Type Type { get; set; }
    public List<Wepon> WeposInList { get; set; }
    }  

public enum Type
{   [Description("Zombie")] Zombie,
    [Description("Human")] Human
}

目前它正在int中保存数据

enter image description here

我想把数据保存为人类和僵尸,而不是用int


您可以将枚举保存到数据库中作为字符串,我同意Dotctor的观点,这不是最好的主意,但是如果需要,您需要做一些更改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class User
{
    public int ID { get; set; }
    public string Name { get; set; }
    public List<Wepon> WeposInList { get; set; }

    [Column("Type")]
    public string TypeString
    {
       get { return Type.ToString(); }
       private set { Type= value.ParseEnum<Type>(); }
    }

    [NotMapped]
    public Type Type { get; set; }
}

将此扩展类添加到项目中。

1
2
3
4
5
6
7
public static class StringExtensions
{
    public static T ParseEnum<T>(this string value)
    {
        return (T)Enum.Parse(typeof(T), value, true);
    }
}

详细信息如下-http://nodogmablog.bryanhogan.net/2014/11/saving-enums-as-strings-with-entity-framework/


据我所知,我遇到了这个问题,老实说,我不知道为什么微软没有添加这个功能(NH可以像往常那样做…)。

任何方法,我通常都会使用const-strings类,比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static class MyEnum
{
    public const string Foo ="Foo";
    public const string Bar ="Bar";
}

public class Client
{

    public string MyVal { get; set; }

    public Client()
    {
        MyVal = MyEnum.Bar;
    }

}

缺点-尽可能简单。

缺点——您松了类型检查(尽管它可以通过编程方式强制执行)。

所以这一次我试着去想一些更有野心的事情。所以我采用了Brian描述的概念(当给定的枚举在整个域中广泛使用时,它有一些缺点)。嗯…我有以下工作:

用于存储值的基本组件类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[ComplexType]
public class DbEnum<TEnum>
{
    public string _ { get; set; }

    public DbEnum()
    {
        _ = default(TEnum).ToString();
    }

    protected DbEnum(TEnum value)
    {
        _ = value.ToString();
    }

    public TEnum ToEnum()
    {
        return _.ToEnum<TEnum>();
    }

    public static implicit operator DbEnum<TEnum>(TEnum value)
    {
        return new DbEnum<TEnum>(value);
    }

    public static implicit operator TEnum(DbEnum<TEnum> value)
    {
        return value.ToEnum();
    }
}

…基本上就足够了。除了ef不支持泛型类型…

这意味着对于每一个枚举,都必须有类似于…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public enum PrivacyLevel
{
    Public,
    Friends,
    Private
}

public class PrivacyLevelEnum : DbEnum<PrivacyLevel>
{
    public PrivacyLevelEnum() : this(default (PrivacyLevel))
    {      
    }

    public PrivacyLevelEnum(PrivacyLevel value) : base(value)
    {
    }

    public static implicit operator PrivacyLevelEnum(PrivacyLevel value)
    {
        return new PrivacyLevelEnum(value);
    }

    public static implicit operator PrivacyLevel(PrivacyLevelEnum value)
    {
        return value.ToEnum();
    }
}

这给了你一些容易生成的锅炉板,例如使用T4模板。

最后你会用到:

1
2
3
4
5
6
public class CalendarEntry : Entity
{

    public virtual PrivacyLevelEnum PrivacyLevel { get; set; } = new PrivacyLevelEnum();

}

但是,由于您已经有了隐式转换,所以类声明是唯一需要了解帮助器类型的声明。


将它们存储为字符串不是一个好主意,但是您可以使用ef enum to look up为枚举创建查找表,并且非常容易使用。


我想,将它们存储为int会更有用,因为您可以很容易地将int从db转换为enum

但是如果你想要的话,有两种方法。您可以将Type.Zombie.ToString()Type.Human.ToString()分别保存到数据库(即"僵尸"),也可以获取您正在使用的DescriptionAttribute的值并保存到数据库。这里描述了如何获取描述。-在这种情况下,它也将是"僵尸",但它可能是你在Description()中写的任何其他东西。

如果使用ToString,则可以使用Enum.Parse返回enum的实例。如果你使用描述,就不那么容易了。


1
modelBuilder.Entity<DataSet>().Property(d => d.SemanticType).HasConversion(new EnumToStringConverter<DataSetSemanticType>());