locked
Recomended replacement for enums? RRS feed

  • Question

  • Since EF4 don't handle enum properties, I'd like to ask what you think is the best replacement for them?

    There are a few options that I can think of.

    1) make a mapped integer property and then expose an unmapped enum property that simply cast the integer value to an enum.

    This approach might look decent at first sight, but you would not be able to query the enum property at DB level, you would have to use the integer property there.


    2) make a mapped integer property only , and pretend that we are java developers and create a class containing constants that correspond to the enum values we wanted.

    This approach lets you query the DB using linq and you can use those constants inside that query, but there is no connection at code level that tells the developer that these specific constants belong together with the integer properyt.
    So we lose domain semantics here.

    3) create entities instead of enum entries, and create an objectset on your context that expose those entities with names using extension methods.

    eg.

    order.Status = context.OrderStatus.Shipped();

    This appraoch keeps the domain semantics and lets us use DB queries.. but it will bloat our solution instead, also, it is very design intrusive, it breaks the purpose of POCO.

    //Roger
    My Blog: http://www.RogerAlsing.com
    Saturday, May 30, 2009 7:28 AM

Answers

  • Roger

    I've just figured out what I think is a pretty good work around when using POCO classes.

    The core to the idea is to:
    1) Use a ComplexType with a single property (Value) that is an int
    2) Where ever you want to have an enum property instead use the ComplexType
    3) In the POCO ComplexType create implicit cast operators two and from your Enum

    if you do this right you can get all this working:

    Task task = new Task {Title = "Post new tip on my blog", Priority = Priority.High};
    
    if (task.Priority == Priority.High)....
    
    var results = from t in ctx.Tasks
                        where t.Priority.Value == (int) Priority.High
                        select t;

    I know this a little vague, but I will be putting a new Tip on my Tips series soon to cover this.

    Alex
    Alex James (Microsoft)
    Friday, June 5, 2009 5:38 AM
    Moderator
  • I do appreciate your effort, but:


    How this is any better than a simple static class with constants?

    public static class Priority
    {
        public const int Low = 0;
        public const int High = 1;
        ...
    }


    In your sample, you loose all the POCO'ness.
    Mapper requirements leak all over the place.

    Also, you rely on implicit casts, there is no intellisense help for this, VS.NET won't tell you that you can assign that enum to the enum wrapper..
    exactly the same way as VS.NET won't tell you that you can assign the above constants to an int property.
    Even your queries leak mapper reuirements.

    With constants it would atleast be:

    var highPriority = 
                from task in ctx.Task 
                where task.Priority ==  Priority.High 
                select task; 

    The whole enum issue might look like a minor problem if you come from a DB centric background, where you define DB schemas first and then pretty much auto generate the DM for it.

    But from a true POCO perspective, this really bad.

    The main reasons why most of us want POCO is for TDD and readabillity.
    And there is no way that I can use your approach in a clean TDD scenario...
    It doesn't add to code readabillity either.

    In my oppinion the current lack of enums is a big fail on the POCO attempts.

    EF4 is wonderfull in all other aspects when it comes to POCO, I was extremely pleased to see that you got plain and proxy POCO and nice support for value objects.
    But the lack of enum support makes the main reason why we wanted POCO in the first place impossible.


    It's like a brand new car with the best interrior and coolest gadgets, but it is missing the right front wheel... and it's impossible to put it back.. with some effort we can mount a cart wheel there instead..


    My Blog: http://www.RogerAlsing.com
    Sunday, June 7, 2009 7:47 AM

All replies

  • This is a good rundown of available options. I cannot think of a solution that does not involve a set of tradeoffs such as those that you describe. I think that it is really up to you to choose the right set of tradeoffs given your preferred programming patterns. For example, if querying the model is only done on an internal basis, then you could declare the int property to be internal and the enum property to be public. You could also declare the property setter private but the getter public, which would enable querying. You could then make the enum public, which would be a bit strange from a programming surface POV, but could get you to a decent set of tradeoffs.

    Best wishes,
     Noam
    This posting is provided "AS IS" with no warranties, and confers no rights.
    Monday, June 1, 2009 4:55 PM
    Moderator
  • Roger

    I've just figured out what I think is a pretty good work around when using POCO classes.

    The core to the idea is to:
    1) Use a ComplexType with a single property (Value) that is an int
    2) Where ever you want to have an enum property instead use the ComplexType
    3) In the POCO ComplexType create implicit cast operators two and from your Enum

    if you do this right you can get all this working:

    Task task = new Task {Title = "Post new tip on my blog", Priority = Priority.High};
    
    if (task.Priority == Priority.High)....
    
    var results = from t in ctx.Tasks
                        where t.Priority.Value == (int) Priority.High
                        select t;

    I know this a little vague, but I will be putting a new Tip on my Tips series soon to cover this.

    Alex
    Alex James (Microsoft)
    Friday, June 5, 2009 5:38 AM
    Moderator
  • As promised I've posted a workaround for the current lake of Enums on my blog

    Tip 23 - How to fake Enums in EF 4

    I hope you find this workaround acceptable
    Cheers
    Alex
    Alex James (Microsoft)
    Friday, June 5, 2009 8:20 PM
    Moderator
  • I do appreciate your effort, but:


    How this is any better than a simple static class with constants?

    public static class Priority
    {
        public const int Low = 0;
        public const int High = 1;
        ...
    }


    In your sample, you loose all the POCO'ness.
    Mapper requirements leak all over the place.

    Also, you rely on implicit casts, there is no intellisense help for this, VS.NET won't tell you that you can assign that enum to the enum wrapper..
    exactly the same way as VS.NET won't tell you that you can assign the above constants to an int property.
    Even your queries leak mapper reuirements.

    With constants it would atleast be:

    var highPriority = 
                from task in ctx.Task 
                where task.Priority ==  Priority.High 
                select task; 

    The whole enum issue might look like a minor problem if you come from a DB centric background, where you define DB schemas first and then pretty much auto generate the DM for it.

    But from a true POCO perspective, this really bad.

    The main reasons why most of us want POCO is for TDD and readabillity.
    And there is no way that I can use your approach in a clean TDD scenario...
    It doesn't add to code readabillity either.

    In my oppinion the current lack of enums is a big fail on the POCO attempts.

    EF4 is wonderfull in all other aspects when it comes to POCO, I was extremely pleased to see that you got plain and proxy POCO and nice support for value objects.
    But the lack of enum support makes the main reason why we wanted POCO in the first place impossible.


    It's like a brand new car with the best interrior and coolest gadgets, but it is missing the right front wheel... and it's impossible to put it back.. with some effort we can mount a cart wheel there instead..


    My Blog: http://www.RogerAlsing.com
    Sunday, June 7, 2009 7:47 AM
  • I hear you Roger.

    I wasn't claiming that this means we don't need to add true support for Enums. What I suggested is not ideal by any stretch of the imagination.

    But you never know some people might be okay with the compromises.

    Cheers
    Alex
    Alex James (Microsoft)
    Sunday, June 7, 2009 4:40 PM
    Moderator