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 c = Color.Red;
Here's the enum wrapper class:
public class EnumWrapper 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 w)
{
if (w == null) return default(TEnum);
else return w.Enum;
}
public static implicit operator EnumWrapper(TEnum e)
{
return new EnumWrapper() { Enum = e };
}
public static implicit operator int(EnumWrapper 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();
}
public int ID { get; set; }
public string Name { get; set; }
public EnumWrapper CheeseColor { get; set; }
}
Mapping:
public class ColorMapping : ComplexTypeConfiguration>
{
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");