One of the things that has not made it into Entity Framework 4.0 beta 1 is Enum support and it is not planned for EF4.
This seems like a strange decision, as it is wrong and not POCO at all if you have to change your classes to work around the lack of enum support in your persistance layer.
Around the internet people suggest that you can just make the property private, and then create a public property that exposes your value as your enum. But that is not quite the solution, as this is not going to work in Linq queries that execute at database level.
While I was still trying to work around this, I came across this post by Alex James that does exactly what I was attempting: to fake enum support.
Lets see how this will look if we implement our Status property on the Order entity to be an enum.
The first thing we are going to do, is to change our Status property in the EF model to be a complex type. We can do that in the designer.
First of all we create the complex type. Right click “Complex Types” in the model browser and choose “Create Complex Type”. We name it OrderStatusWrapper and add a scalar Int32 property called “Value” to it.
Then we delete the scalar Status property from the Order entity, and add a complex property instead. We name it Status like the old one, and in properties we set the type to “OrderStatusWrapper”. If we build now, the validator will complain that we forgot to map the property, so we get the table mapping window, and map the Status integer to the “Value” integer on our complex property.
Now we add the enum as usually:
3 public enum OrderStatus
4 {
5 OrderCreated,
6 OrderPayed,
7 OrderShipped
8 }
Now we have to implement our OrderStatusWrapper, and make it do some work behind the scenes for us:
1
2 public class OrderStatusWrapper
3 {
4 private OrderStatus _status;
5
6 public int Value
7 {
8 get { return (int)_status; }
9 set { _status = (OrderStatus)value; }
10 }
11 public OrderStatus EnumValue
12 {
13 get { return _status; }
14 set { _status = value; }
15 }
16
17 public static implicit operator
18 OrderStatusWrapper(OrderStatus status)
19 {
20 return new OrderStatusWrapper { EnumValue = status };
21 }
22
23 public static implicit operator
24 OrderStatus(OrderStatusWrapper statusWrapper)
25 {
26 if (statusWrapper == null) return
27 OrderStatus.OrderCreated;
28 else return statusWrapper.EnumValue;
29 }
30 }
31
To do this we need to do an implicit operator overloading – that is an implicit conversion between OrderStatusWrapper and OrderStatus, creating the illusion that Status really is an OrderStatus enum value.
Now we can actually do this:
24 Order o = new Order();
25 o.CreatedDate = DateTime.Now;
26 o.Status = OrderStatus.OrderCreated;
27 o.Customer = custRep.First(x => x.Id == 1);
28 orderRep.Add(o);
And we can use it in a query like so:
24 var orders = from o in orderRep.GetAll()
25 where o.Status == OrderStatus.OrderCreated
26 select o;
This is a fairly decent workaround, but it still bothers me that we have to declare our property with the type of the wrapper, and that we have to clutter our code with wrappers. This is behaviour to accommodate our choice of ORM.
So we do need real enum support, but intill we do we seem to get by with this.
Resources:
Remember Me