2

when will Microsoft's EF6 team add full enum support?

Sample code snippets are below. vs2013, EF6.0.1

Since EF5, presumably EF had support for enum.

There is however a GOTCHA: http://msdn.microsoft.com/en-us/data/hh859576
not all underlying types are supported.
Only: Byte, Int16, Int32, Int64 , or SByte.

imho, Microsoft fails programmers here in at least three ways:
(a) types like ulong are valid and should be supported.
(b) Visual Studio gives zero warning when columns are not created.
(c) one gets to assign to the Poco fields and gets lulled into thinking that her/his code is working.

Yes, testing should reveal the issue, as it did for me, however, i almost missed it because my SQL table has a large number of columns.

at http://msdn.microsoft.com/en-us/data/ee712907, the EF team suggests we should post EF questions here at SO.

Here's the code:

namespace EF6enums
{
    public enum Country : long { Canada = 1, England = 2 }

changing "long" to "ulong" breaks the code.

public class EF6Poco
{
    public Int32  ID { get; set; }
    public String City { get; set; }
    public Country CountryEnum { get; set; }
}

We are using Code First:

public class EnumTestContext : System.Data.Entity.DbContext
{
    public System.Data.Entity.DbSet<EF6Poco> EF6Pocos { get; set; }
}

Here's the Main method:

    class Program
    {
        static void Main(string[] args)
        {
            using (var context = new EnumTestContext())
            {
                context.EF6Pocos.Add(new EF6Poco
                   { City = "Wasaga Beach",
                     CountryEnum = Country.Canada });
                context.SaveChanges();
            }
            Console.WriteLine("Done");
            Console.ReadLine();
    }
}
}   //      namespace EF6enums
gerryLowry
  • 2,626
  • 5
  • 35
  • 44
  • EF is open source: http://entityframework.codeplex.com/ so feel free to add support :) – markmnl Dec 10 '13 at 06:45
  • @markmnl see http://msdn.microsoft.com/en-us/magazine/dn532202.aspx (2013 December): Julie Lerman writes: "you can also contribute source to EF6 (though with complete oversight by the EF team)." Microsoft is still in control. FWIW. – gerryLowry Dec 10 '13 at 06:52
  • sure, but what has that got to do with it - you don't need your changes to be accepted for _you_ to use it! – markmnl Dec 10 '13 at 06:54
  • @gerryLowry If your pull requests makes sense and it does not break anything it is very likely to be accepted. Many pull requests have been accepted for EF already. Also this is quite the wrong place to ask the question *When will Microsoft...*. Ask directly, ask in the EF forum. – user3038092 Dec 10 '13 at 07:18
  • 5
    This question appears to be off-topic because it is hardly a code-related question, and it can't be answered here as StackOVerflow. For feature request you go to https://data.uservoice.com/forums/72025-entity-framework-feature-suggestions/. – Gert Arnold Dec 10 '13 at 07:34
  • @GertArnold given that i'd like to use it in my code, of course, imho, it is code related; also, Julie Lerman says that this is where we should ask EF questions in her December 2013 MSDN magazine article. – gerryLowry Dec 10 '13 at 15:00
  • @user3038092 Julie Lerman says that this is where we should ask EF questions in her December 2013 MSDN magazine article; if you look at http://msdn.microsoft.com/en-us/data/aa937723, it explicitly states "Ask a Question Find out how to get help from the experts and contribute to the data community on Stack Overflow.". – gerryLowry Dec 10 '13 at 15:03
  • @GertArnold it is a "technical" question: http://www.merriam-webster.com/dictionary/technical – gerryLowry Dec 10 '13 at 15:12
  • Sorry if I somehow misled you, @gerryLowry. I guess the sticking point is about what kinds of questions go here on SO and what doesn't. This might help: http://meta.stackoverflow.com/help/dont-ask. +1 on uservoice or codeplex for suggestions to improve EF. – Julie Lerman Dec 10 '13 at 15:36
  • @JulieLerman FWIW, no apology necessary; clarity is important; imho, more needs to be said at http://msdn.microsoft.com/en-us/data/aa937723 and http://msdn.microsoft.com/en-us/data/hh913619 because that is where clarity is lacking. Julie, perhaps i should have titled my so question "how do i use ulong in EF6 as my enum type"; however, i suspect i'd get answers like "you can't". B-( – gerryLowry Dec 10 '13 at 15:45
  • So you're really looking for some guidance to workaround the limitaton that EF enums don't support ulong (with the additional -- & totally understandable -- gripe that EF enums don't support all of the types that .NET supports for enums). The underlying problem is that EF doesn't map to unsigned types at all. So it's not even specific to the enum support. Here's another SO conversation with some code ideas http://stackoverflow.com/questions/19116153/how-to-use-an-existing-enum-with-entity-framework-db-first – Julie Lerman Dec 10 '13 at 16:52
  • and a conversation about unsigned types (possible support post EF6...?) on EF codeplex site...http://entityframework.codeplex.com/workitem/1489 – Julie Lerman Dec 10 '13 at 16:54
  • I wonder what is the scenario where ulong enums are useful (seems like a lot of values). I don't think long/ulong matters for flags. Note that the limitation comes from the limitation of the EDM type system which does not allow unsigned numeric types and therefore does not allow enums of unsigned underlying type. (While I am not sure how useful ulong enums I agree in general that the limitation itself is kind of ridiculous). – Pawel Dec 10 '13 at 17:32

1 Answers1

4

Not supporting ulong enums is a result of EDM not supporting unsigned numeric types in general. Unsigned numeric types can be useful but I am not sure if ulong enums are useful. If you want to use enum type as a bit field then the sign should not matter - in this case you care only about bits and unsigned and its counterpart signed enum type has the same number of bits so you can use either. The [Flags] attribute is also interesting - the only thing it affects is how the .ToString() works (and maybe .Parse() as this is the opposite operation). It does not do anything special as far as using the enum type goes - i.e. you can do the same operations on enums with and without the [Flags] attribute (be it bitwise operations or non-bitwise operations) and you should get the same results regardless of the presence of the attribute.

As far as ignoring properties of unsigned numeric types silently is concerned we had a long discussion whether to leave this is as is or throw an exception. We decided to leave it as is since changing it to throw would be a breaking change and would mean that models created in EF4.x or EF5 now would be considered invalid in EF6. Also, in general Code First tends to ignore properties of types it does not understand so the current behavior is kind of inline with the general principle. The real issue here is that people are unaware that EF does not understand unsigned numeric types and are taken by surprise. I agree that the expectation that EF understands unsigned numeric types is reasonable and it is unfortunate they are not supported in EF.

Pawel
  • 31,342
  • 4
  • 73
  • 104
  • thank you for explanation, as well as your participation via Twitter. FWIW, i do not get why a decision to leave out native unsigned integral values would have been made in the first place; what surprises me even more it that this is the first time i've bumped into this restriction ... continued – gerryLowry Dec 10 '13 at 21:02
  • Fabricated example: ScottGu can not play on this [Flags] team because the c# compiler will not allow him. `[Flags] public enum EF6Team : sbyte { ArthurVickers = 1, BriceLambson = 2, DiegoViega = 4, JulieLerman = 8, PawelKadluczka = 16, RowanMiller = 32, UnaiZorrilla = 64, ScottGu = 128 }` -- if we make the `sbyte` into a `byte` EF6 prevents the entire team from playing. B-( – gerryLowry Dec 10 '13 at 21:06
  • FWIW, i wanted to use a `ulong` to have the extra bit available for an application that i am currently coding using [Flags] ... yes, i can code around losing a flag to EF6 ... OTOH, i really do feel sorrow for that orphaned bit. `B-(` More importantly, for smaller enums using [Flags], an eighth flag forces use of an Int16 and a 16th flag forces use of an Int32. – gerryLowry Dec 10 '13 at 21:19
  • @gerryLowry: you are not loosing the value. 128 is out of range for sbyte indeed but coming from bit representation you are looking for 0%10000000 which represents -128 - so you enum should be: `ScottGu = -128` (true, looks weird). I think the unsigned numeric types might have been omitted because they were non-CLS compliant but don't know for sure. (btw. funnily SByte/Byte are both supported by EF so you should use short in your example :)) – Pawel Dec 10 '13 at 21:53
  • (a) you're correct...i failed to notice `Byte` at the beginning of the list i cut & pasted into my question. (b) using `-128` feels schizophrenic; i get the hardware aspect but if i had designed System.Enum, i would have prevented `-128` when [Flags] is applied given that no positive power of 2 yields a negative number while all negative powers of 2 yield a non-integer result. (c) in EF, i find it interesting that `Byte` gets special treatment but not the other unsigned integal value types; OTOH, give people like me a `Byte`, we'll eventually want a `ulong`. `B-)` Thank you. – gerryLowry Dec 11 '13 at 02:52
  • Is there a way to search an SQL server using EF by filtering results to a bit flag? I.e. `Customers.Where(c => (c.Flags | RedFlagMask) > 0);`. – Shimmy Weitzhandler Jan 26 '15 at 00:43
  • 1
    @Shimmy - I would think the query should work the way you wrote it if it doesn't you could try casting 'c.Flags' to the underlying enum type. – Pawel Jan 26 '15 at 01:26
  • @Pawel it's an `int`, not `Enum`... – Shimmy Weitzhandler Jan 26 '15 at 22:32
  • 2
    @Shimmy - not the base type but the underlying type. Enums in .NET are backed by an integral type. As per enum C# reference (https://msdn.microsoft.com/en-us/library/sbbt4032.aspx): "Every enumeration type has an underlying type...". So if your query does not work directly you could try `Customers.Where(c => ((int)c.Flags) | RedFlagMask > 0)` if the underlying type of you enum is int (which is the default one if you don't specify your own. – Pawel Jan 27 '15 at 02:23