How to save enum in database as string

后端 未结 6 664
北恋
北恋 2020-12-29 02:59

This is my Model Class where we have a Type which could be a Zombie or Human

public class User
{
    public int ID { get; set; }
    public string Name { ge         


        
相关标签:
6条回答
  • 2020-12-29 03:27

    You can save the enum to the db as a string, and I agree with dotctor that it is not the best idea, but if you need to, you need to make a few changes.

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

    Add this extension class to your project.

    public static class StringExtensions
    {
        public static T ParseEnum<T>(this string value)
        {
            return (T)Enum.Parse(typeof(T), value, true);
        }
    }
    

    Full details are here - http://NoDogmaBlog.bryanhogan.net/2014/11/saving-enums-as-strings-with-entity-framework/

    0 讨论(0)
  • 2020-12-29 03:33

    In Entity Framework Core you can specify the built-in conversion:

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

    More details here.

    0 讨论(0)
  • 2020-12-29 03:36

    It's not a good idea to store them as string but you can create look up tables for your enums with ef enum to lookup and it is very easy to use.

    0 讨论(0)
  • 2020-12-29 03:39

    I had this problem as far as I remember and honestly I don't know why didn't MS add this feature (NH can do it like since always..).

    Any ways, what I usually did is use const strings classes like:

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

    Cons - as simple as can be.

    Downsides - you loose type checking (though it could be enforced programmatically).


    So this time I tried to think of something more ambitious. So I took the concept described by Brian (which has some downsides when e.g. a given enum is used widely across the domain). And well.. I got the following working:

    A base component class to store the values:

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

    ... which would be basically sufficient.. except EF doesn't support generic types...

    This means for every enum you have to have something like...

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

    Which gives you some boiler-plate that could be easily generated e.g. using T4 templates.

    Which finally ends you up with using:

    public class CalendarEntry : Entity
    {
    
        public virtual PrivacyLevelEnum PrivacyLevel { get; set; } = new PrivacyLevelEnum();
    
    }
    

    But since you have implicit conversion in place, class declarations are the only ones to be aware of the helper types.

    0 讨论(0)
  • 2020-12-29 03:39

    I thing, that it is much more useful to store them as int because you can then cast the int from DB very easily to the enum.

    But if it what you desire, there are two approaches. You can save Type.Zombie.ToString() (or Type.Human.ToString() respectively) to database (which will be "Zombie"), or you can obtain the value of DescriptionAttribute, which you are using and save that to the DB. How to get the description is described here. - It will be also "Zombie" in this case, but it may be whatever else you write in the Description().

    If you use ToString you can then use Enum.Parse to get the instance of the enum back. If you use the description, it is not that easy.

    0 讨论(0)
  • 2020-12-29 03:48

    Explicit enum to string conversions would make your code messy and you'd have to keep parsing values. The same goes for lookup tables. Just add [Column] attribute to your enum field and specify TypeName as nvarchar (for SQL) or varchar (for postgres). Worked for me like a charm. In your case, for example :

    public class User
    {
        public int ID { get; set; }
    
        public string Name { get; set; }
    
        [Column(TypeName = "nvarchar(20)")]
        public Type Type { get; set; }
    
        public List<Wepon> WeposInList { get; set; }
    
        }  
    

    You can read more about it in the official documentation here

    0 讨论(0)
提交回复
热议问题