EF 4.1 Code First - map enum wrapper as complex type

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");

15
задан James Kolpack 10 May 2011 в 22:46
поделиться