Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework - Persisting Enums Generically?

Trying to create a workaround for processing Enums in the Entity Framework using Generics, but EF doesn't seem to care for generic properties. For example:

public enum MyEnum
{
    One, Two, Three
}

public class SomePOCOWithEnum
{
      // I want this to persist as an int, but EF doesn't like generics.
      public EnumWrapper<MyEnum> MyEnumProperty { get; set; }
}

The intention is to have the enum persist as an INT in the database. Is there any special way using fluent or perhaps some other mechanism method whereby I can create said generic class and have it persist as an INT to the database within EF?

The intention is to keep things generic as I have about two dozen enums that need persisting, and I'd rather not write individual wrapper classes for each of them.

Here is the generic EnumWrapper class, which demonstrates what I'd like to accomplish: implicit conversion to enum, but persistence as an int:

public class EnumWrapper<T> where T : struct
{
    private T enumValue;
    public int Value
    {
        get { return Convert.ToInt32(enumValue); }
        set { enumValue = (T)Enum.Parse(typeof(T), value.ToString()); }
    }

    public T EnumValue
    {
        get { return enumValue; }
        set { enumValue = value; }
    }

    public static implicit operator T(EnumWrapper<T> wt)
    {
        return wt.EnumValue;
    }

    public static implicit operator EnumWrapper<T>(T t)
    {
        return new EnumWrapper<T>() { EnumValue = t };
    }

    public override string ToString()
    {
        return enumValue.ToString();
    }
}
like image 512
Dan McCann Avatar asked Dec 30 '11 09:12

Dan McCann


1 Answers

As sinelaw has already pointed out, EF5 has explicit support for Enums, but if you cannot migrate to it for whatever reason, the approach I've taken might work for you.

For this example, let's say the table is named "Email" and we have a column named "Priority". Setup your column as an int as you would normally do. Next, in your entities project, create an enums class that maps to your int values:

public enum EmailPriorityEnum
{
    Now = 100,
    Soon = 1000,
    Whenever = 10000
}

Finally, in your entities project, create a partial class file matching your entity and manually map the enum there:

public partial class Email
{
    public EmailEnums.EmailPriorityEnum EmailPriority
    {
        get { return (EmailEnums.EmailPriorityEnum)Priority; }
        set { Priority = (int)value; }
    }
}

From there on out, your code can reference this property transparently. The primary drawbacks to this approach are:

  1. You have to be careful that all possible values are mapped in the enum with the proper ids. For enums that change often this becomes problematic.
  2. Developers will still have access to the underlying column unless you change the accessibility and could conceivably bypass the enums and use whatever value they like.
like image 143
Heather Avatar answered Sep 21 '22 15:09

Heather