patterncsharpModerate
Dealing with Entity Framework's lack of enum support
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
Repository
View Model
Enum Replacement Class
My Personal Assessment
Pros:
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:
Obviously
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?
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.