Please navigate to the bottom of the page for Table of Contents

Friday, March 22, 2013

Entity Framework Interview Question - Explain ENUM usage in EF5

Entity Framework 5 introduced support for Enum’s amongst other new features. This was a long awaited feature by the community. In this post, we will explore how enums work with entity framework, how can you code them, how to use them, how they are represented in the database, etc.

Question: Write code to demonstrate ENUM usage in Entity Framework.

For this exercise, please make sure that your project references at least version 5 of Entity Framework. You can use NuGet to add that to your project.

Model

In Entity Framework, an enumeration can have the following underlying types: Byte, Int16, Int32, Int64 , or SByte. I chose 3 different enum types to highlight the differences in database representation for different enum types.
    public enum DefaultEnum
    {
        Red = 1,
        Blue = 2,
        Green = 3
    }

    public enum ByteEnum : byte
    {
        RedByte,
        BlueByte,
        GreenByte
    }

    public enum ShortEnum : short
    {
        RedShort,
        BlueShort,
        GreenShort
    }

Now, let’s define our Account class that uses these enums.
    public class EnumDemoAccount
    {
        [Key]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
        public string Name { get; set; }

        // our enum fields
        public DefaultEnum DefaultEnum { get; set; }
        public ByteEnum ByteEnum { get; set; }
        public ShortEnum ShortEnum { get; set; }
    }

As you can note, I am generating the Identity column as auto-incrementing (bonus).

Context


Our Context definition is pretty standard for this example. All I am telling the system is to create a database with the name I have given (instead of it choosing one based on namespace + class.
    public class AccountContext : DbContext
    {
        public DbSet<EnumDemoAccount> EnumDemoAccounts { get; set; }

        public AccountContext() : base("EFDemoDb")
        {}
    }

I also like to like to create a context initializer for test projects so that I always have a clean database for each run:
    public class DatabaseContextInitializer : 
        DropCreateDatabaseAlways<AccountContext>
    {
        protected override void Seed(AccountContext dbContext)
        {
            base.Seed(dbContext);
        }
    }

Test code


The test code is simple as well. We first set our initialization strategy, create a context, add a few records and see how things look.
        static void Main(string[] args)
        {
            // initialization 
            Database.SetInitializer<AccountContext>
                (new DatabaseContextInitializer());

            // create a new context
            AccountContext ac = new AccountContext();

            // add a couple of test entries
            ac.EnumDemoAccounts.Add(
                new EnumDemoAccount()
                {
                    Name = "First",
                    DefaultEnum = DefaultEnum.Blue,
                    ByteEnum = ByteEnum.GreenByte,
                    ShortEnum = ShortEnum.RedShort
                });

            ac.EnumDemoAccounts.Add(
                new EnumDemoAccount()
                {
                    Name = "Second",
                    DefaultEnum = DefaultEnum.Green,
                    ByteEnum = ByteEnum.RedByte,
                    ShortEnum = ShortEnum.BlueShort
                });

            // save to db
            ac.SaveChanges();

            // display
            foreach (var account in ac.EnumDemoAccounts)
            {
                Console.WriteLine(
                    "Name: {0}\n\tDefaultEnum:{1}\n\tByteEnum:{2} \n\tShortEnum: {3}",
                    account.Name,
                    account.DefaultEnum,
                    account.ByteEnum,
                    account.ShortEnum);
            }

            Console.ReadKey();
        }

Output


Now let’s review the output we got:

EnumDemo-output

As you can see, the enum values survived the round trip to the database. Wonderful! And they are all strongly typed so we can use them in our regular programming.

Database


Understanding what happened on the database side is equally important. Remember, we created 3 different enum types in our model – int, short and byte. Does the data type of the enum make any difference in the storage scheme? You bet! Let’s see how Entity Framework internally represents these types to the database:

EnumDemo-db-table

Note that the default enum data type (int) remained as int. Byte was translated as tinyint and Short as smallint. So, if you are using enums, think hard about your use cases and choose the appropriate datatype for your enums.

And finally, to round things up, let’s see what data values are stored in our database:

EnumDemo-db-query-output

No surprises here. Auto generated identity column, proper values for our enums. Things look good. Hoping that this post has given you a good starting point about enums in Entity Framework 5.

1 comment: