I'm trying to build a generic solution to the problem of enums with EF 4.1. My solution is basically a generic version of How to fake enums in ef 4. The enum wrapper class works wonderfully in the rest of the code and allows code like:
EnumWrapper<Color> c = Color.Red; Here's the enum wrapper class:
public class EnumWrapper<TEnum> where TEnum : struct, IConvertible { public EnumWrapper() { if (!typeof(TEnum).IsEnum) throw new ArgumentException("Not an enum"); } public TEnum Enum { get; set; } public int Value { get { return Convert.ToInt32(Enum); } set { Enum = (TEnum)(object)value; } } public static implicit operator TEnum(EnumWrapper<TEnum> w) { if (w == null) return default(TEnum); else return w.Enum; } public static implicit operator EnumWrapper<TEnum>(TEnum e) { return new EnumWrapper<TEnum>() { Enum = e }; } public static implicit operator int(EnumWrapper<TEnum> w) { if (w == null) return Convert.ToInt32(default(TEnum)); else return w.Value; } } enum:
public enum Color { red = 1, green = 2, blue = 3 } POCO:
public class ChickenSandwich { public ChickenSandwich() { CheeseColor = new EnumWrapper<Color>(); } public int ID { get; set; } public string Name { get; set; } public EnumWrapper<Color> CheeseColor { get; set; } } Mapping:
public class ColorMapping : ComplexTypeConfiguration<EnumWrapper<Color>> { public ColorMapping() { Ignore(x => x.Enum); Property(x => x.Value); } } I've also tried mapping it on the ChickenSandwich's EntityTypeConfiguration like this:
Property(x => x.CheeseColor.Value).HasColumnName("CheeseColor"); If I leave it up to the ColorMapping and do no explicit mapping on the ChickenSandwichMapping, it just doesn't put it in the database. If I map it the x.CheeseColor.Value way, I get the dreaded:
System.InvalidOperationException: The configured property 'CheeseColor' is not a declared property on the entity 'ChickenSandwich'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property..
Edit
I wasn't able to get the generic version of the enum wrapper working, so I've gone with writing individual wrappers. It's not exactly what I wanted because it violates the DRY principle, but it does allow me to query the column as an enum.
[ComplexType] public class ColorWrapper { [NotMapped] public Color Enum { get; set; } public int Value { get { return (int)Enum; } set { Enum = (Color)value; } } public static implicit operator Color(ColorWrapper w) { if (w == null) return default(Color); return w.Enum; } public static implicit operator ColorWrapper(Color c) { return new ColorWrapper { Enum = c }; } } I had to use the ColorWrapper on the ChickenSandwich class. It works more or less transparently. Then had to add this to my mapping class constructor to get the column name I wanted:
Property(x => x.CheeseColor.Value).HasColumnName("CheeseColorId");