How to save enum in database as string
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/
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.
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.