HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpModerate

Dealing with Entity Framework's lack of enum support

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
withenumdealinglacksupportframeworkentity

Problem

I'm using Entity Framework Code First CTP 5 for a current project. There is still no enum support in Entity Framework so this is what I am using in order to avoid having magic numbers or casts littered throughout my code.

Simplified Example:

Domain Model Consumed by Code First

public class Address
{
    // This would normally be an enum
    public int Type { get; set; }
}


Repository

public class AddressRepository
{
    public Add(Address address)
    {
        // Compare using enum semantics
        if (address.Type == AddressType.Home)
            // Do something

        context.Add(address);
    }
}


View Model

public class AddressVM
{
    // Using the AddressType class for the view model
    public AddressType Type { get; set; }     

    public AddressVM(Address address)
    {
        this.Type = address.Type;
    }
}


Enum Replacement Class

public interface IEnumClass
{
    List Properties { get; }
}

public class AddressType : IEnumClass
{
    public static int Home { get { return 0; } }
    public static int Work { get { return 1; } }

    public List Properties { get { return properties; } }

    private List properties;
    private int id;

    public AddressType()
    {
        SetProperties();
    }
    public AddressType(int id)
    {
        this.id = id;
        SetProperties();
    }

    private void SetProperties()
    {
        properties = this.GetType().GetProperties(BindingFlags.Public|BindingFlags.Static)
            .Select(x => x.Name).ToList();
    }

    public static implicit operator AddressType(int id)
    {
        return new AddressType(id);
    }

    public static implicit operator String(AddressType addressType)
    {
        return addressType.properties[addressType.id];
    }

    public static implicit operator int(AddressType addressType)
    {
        return addressType.id;
    }
}


My Personal Assessment

Pros:

  • Allows me to write business rules without using magic numbers



  • Uses the

Solution

I keep seeing all these really complex solutions to the lack of enum support, but most make things tricky when taking into account that next entity framework release is probably going to have enum support.

Here's my solution. A sample class, before our workaround:

public class Widget
{
    public int ID { get; set; }
    public Status Status { get; set; }
}


Obviously Status won't be saved as it's an enum, and if we provide a fancy workaround, things will probably break when we upgrade to the next entity framework release, as it'll suddenly start trying to read and write that property. So we do the following:

public class Widget
{
    public int ID { get; set; }
    [NotMapped] // stop future entity frameworks from accidentally using this column
    public Status Status { get; set; }

    [Column("Status")]
    private int StatusEnum
    {
        get { return (int)Status; }
        set { Status = (Status)value; }
    }
}


The new property is private so we can't see it externally, so it doesn't exist to the outside world for all intents and purposes. The entity framework can see it as you've marked it with a [Column] attribute and so it'll be found via reflection. The original enum column will be skipped even if we upgrade to a later version of the framework, and then all we have to do is remove those few lines of workaround code and things should still work seamlessly.

The result?

  • The class looks the same to anything consuming it, but now enums are saved and loaded



  • No additional code complexity



  • Future-proofed against entity framework upgrades



  • Super easy to remove the additional code when upgrading to a version of the framework that supports enum persistence

Code Snippets

public class Widget
{
    public int ID { get; set; }
    public Status Status { get; set; }
}
public class Widget
{
    public int ID { get; set; }
    [NotMapped] // stop future entity frameworks from accidentally using this column
    public Status Status { get; set; }

    [Column("Status")]
    private int StatusEnum
    {
        get { return (int)Status; }
        set { Status = (Status)value; }
    }
}

Context

StackExchange Code Review Q#1162, answer score: 10

Revisions (0)

No revisions yet.