1

Imagine you have two tables - Orders and OrderStates - and the obvious relationship that every Order is in a particular state. Let's say that both have a int primary key Id. The order states will never change and are in database for only design and ui purposes. That being said you would want to create an Enum type representing the order states. However, the entity framework has already generated classes using the order state int value/key.

What are the possible solutions for given problem? Remeber that the question is about EF1 or EF .NET 3.5 if you will and that you start with a already designed database (database first approach). I work with the old version because I am currently developing an application for Sharepoint 2010 which runs on .NET 3.5.

I have only found solutions for EF4 or higher like this one: Enum Support for Entity Framework Database First

To make it clearer, I would like to avoid casting the int all the time. The generated code forces you to write either:

 (OrderStates)OrderState.State == OrderState.StateX;

OR

 OrderState.State == (int)OrderState.StateX;

It could be ok in case you get to such a situation just once, but that is usually not the case. Also the enum's code readability is higher than just some int value.

Community
  • 1
  • 1
Santhos
  • 3,348
  • 5
  • 30
  • 48

3 Answers3

1

Alright, so you can't overload the operators on an enum. However, you could build a class that overloads the operators you could go both ways. Consider the following code:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(1 == MyEnum.Value0);
        Console.WriteLine(2 == MyEnum.Value2);
    }
}

public class MyEnum
{
    public static readonly MyEnum Value0 = 0;
    public static readonly MyEnum Value1 = 1;
    public static readonly MyEnum Value2 = 2;

    private MyEnum() { }

    private int _val;
    private MyEnum(int val)
    {
        _val = val;
    }

    public static implicit operator int(MyEnum val)
    {
        return val._val;
    }

    public static implicit operator MyEnum(int val)
    {
        return new MyEnum(val);
    }
}

This outputs:

False
True

So, if you built a class named OrderStates that overloaded the operators like I did here and then listed all states, you'd effectively get an enum with the comparison overloads.

Mike Perrenoud
  • 66,820
  • 29
  • 157
  • 232
  • This isn't really a nice solution. You have to write quite a lot for a single enum. – Santhos Nov 29 '13 at 16:25
  • @Santhos, I never claimed it was *elegant.* I'm just letting you know that it's the workaround for where you're at. The `enum` type **cannot** be overloaded. Further, if you inspected the code generated by the EF for what you want, it's actually performing a cast. It's just that the code is generated so in that case you don't care. – Mike Perrenoud Nov 29 '13 at 16:31
  • But that is exactly the difference. If the cast was generated in the class I would be completely satisfied since I wouldn't have to write any additional code and I would have nice looking conditions. I simply like readable code. If I wanted ugly code, I would write the casts manually, it is not "such a big deal". – Santhos Nov 29 '13 at 16:47
  • @Santhos, the code outside of the class that acts as the enum looks just as clean as you desire. With the attitude you have at the moment there is no solution to your problem. You're stuck using a specific framework version because you're building a SharePoint add in. There's nothing anybody can do about that. Further, the designers of the language didn't implement this for some reason. Wouldn't you rather have one class that's a bit of a pain than casts everywhere in your code? – Mike Perrenoud Nov 29 '13 at 16:55
  • possibly yes. I still have a feeling that there could be a slightly nicer solution with generics or something. I will give it a thought. I also found out that it might be possible to simply overwrite the ints with the enums and that the code generation does not overwrite it back to ints. However, I have to test it first. – Santhos Nov 29 '13 at 17:04
1

A simple extension method should yield some fairly readable code:

public static class OrderStatesExtensions
{
    public static bool Is(this int n, OrderStatesstate)
    {
        return (States) n == state;
    }

    public static bool Is(this OrderStates state, int n)
    {
        return n.Is(state);
    }
}

// usage
order.State.Is(OrderStates.Something)

Though, to be fair, I'm not sure how this will work when it's sent to the server; i.e., this may only be useful after the results have been returned.

Austin Salonen
  • 49,173
  • 15
  • 109
  • 139
  • +1, this is another solution I had considered when deciding which way to go. I do believe you're right that it will only work client-side, but I'm not sure mine would be any different in that regard. – Mike Perrenoud Nov 29 '13 at 17:30
  • There is no need to create extension classes when the generated classes are marked as partial exactly for such purposes imo. – Santhos Dec 16 '13 at 23:04
0

The approach I have used and it is not mentioned here is that I created partial class of the Order (because EF generates the classes as partials) and then I put a method there which does the cast. You have to do it in every class that uses the enum, or any other enum. However, you have to define those enums by yourself anyway and at least it is quite clean.

public partial class Order
{
    public OrderState GetOrderState()
    {
        return (OrderState)this.OrderState.Id;
    }
}
Santhos
  • 3,348
  • 5
  • 30
  • 48