Note that there are some explanatory texts on larger screens.

plurals
  1. POEF 4.1 Code First - map enum wrapper as complex type
    text
    copied!<p>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 <a href="http://blogs.msdn.com/b/alexj/archive/2009/06/05/tip-23-how-to-fake-enums-in-ef-4.aspx">How to fake enums in ef 4</a>. The enum wrapper class works wonderfully in the rest of the code and allows code like:</p> <pre><code>EnumWrapper&lt;Color&gt; c = Color.Red; </code></pre> <p>Here's the enum wrapper class:</p> <pre><code>public class EnumWrapper&lt;TEnum&gt; 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&lt;TEnum&gt; w) { if (w == null) return default(TEnum); else return w.Enum; } public static implicit operator EnumWrapper&lt;TEnum&gt;(TEnum e) { return new EnumWrapper&lt;TEnum&gt;() { Enum = e }; } public static implicit operator int(EnumWrapper&lt;TEnum&gt; w) { if (w == null) return Convert.ToInt32(default(TEnum)); else return w.Value; } } </code></pre> <p>enum:</p> <pre><code>public enum Color { red = 1, green = 2, blue = 3 } </code></pre> <p>POCO:</p> <pre><code>public class ChickenSandwich { public ChickenSandwich() { CheeseColor = new EnumWrapper&lt;Color&gt;(); } public int ID { get; set; } public string Name { get; set; } public EnumWrapper&lt;Color&gt; CheeseColor { get; set; } } </code></pre> <p>Mapping:</p> <pre><code>public class ColorMapping : ComplexTypeConfiguration&lt;EnumWrapper&lt;Color&gt;&gt; { public ColorMapping() { Ignore(x =&gt; x.Enum); Property(x =&gt; x.Value); } } </code></pre> <p>I've also tried mapping it on the ChickenSandwich's EntityTypeConfiguration like this:</p> <pre><code>Property(x =&gt; x.CheeseColor.Value).HasColumnName("CheeseColor"); </code></pre> <p>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:</p> <blockquote> <p>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..</p> </blockquote> <hr> <p><strong>Edit</strong></p> <p>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 <a href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself">DRY</a> principle, but it does allow me to query the column as an enum. </p> <pre><code>[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 }; } } </code></pre> <p>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:</p> <pre><code>Property(x =&gt; x.CheeseColor.Value).HasColumnName("CheeseColorId"); </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload