# Sunday, September 02, 2012

Entity Framework 5 + Enumerations => What’s not to love?

Entity Framework 5 now supports enumerations (when using Visual Studio 2012 and targeting the .NET 4.5 framework).

So let’s have a look. We’ll create a table called Planet with a name and a field to indicate whether it is habitable.

CREATE TABLE [dbo].[Planets](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](max) NOT NULL,
    [Habitable] [smallint] NOT NULL,
 CONSTRAINT [PK_Planets] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
END

Note: the data type for ‘Habitable’ is a smallint.

Next we’ll generate an entity data model from the database. Nothing exciting, since our database has just one table.

image

When we inspect the properties of the ‘Habitable’ property we see that, as expected, it is mapped to an Int16 (short).

image

Instead of a short we want to map the field to the following enumeration (note that having the enumeration be of type ‘short’ is significant, the type you select for your enum needs to match the column type in the database):

public enum HabitableEnum : short
{
  Humanoids = 1,
  Insects = 2,
  Droids = 3,
  None = 4,
  All = 5
}

In order to so, we need to update the model with information about the enum. This is done in the Model Browser.

image

Look for the “Enum Types” node and right click to add an Enum to the conceptual model.

image

We can have a locally defined enumeration (to be used in the T4 code generation) or we can refer to the previously defined enumeration by checking the “Reference external type” checkbox.

After adding the enumeration to the model we can now go and update the “Habitable” property in the conceptual model, the enumeration will now be displayed in the type listbox.

image

If we now browse through the generated code (click the triangle next to the Edmx file in your solution explorer) you’ll see that the generated class for “Planet” is now using the enumeration.

public partial class Planet
{
    public int Id { get; set; }
    public string Name { get; set; }
    public EF5Demo.Xyz.HabitableEnum Habitable { get; set; }
}
Should you not see the change, then right click on <yourmodelname>.tt and choose “Run Custom Tool” in order for the T4 template to regenerate the classes.

We can now write some code to insert and query the database. Here is an example:

var ctx = new StarWarsEntities();
Planet p1 = new Planet() { Name = "Tatooine", Habitable = HabitableEnum.Droids };
Planet p2 = new Planet() { Name = "Coruscant", Habitable = HabitableEnum.Humanoids };
 
ctx.Planets.Add( p1 );
ctx.Planets.Add( p2 );
 
ctx.SaveChanges();
 
var query = from p in ctx.Planets
            where p.Habitable == HabitableEnum.Humanoids
            select p;
 
foreach ( var p in query )
{
  Console.WriteLine( p.Name + " - " + p.Habitable );
}
 
Console.ReadLine();

When we run it:

image

That’s all there’s to it. Using enumerations with Entity Framework 5.

But wait, would it not be nice if we could use byte based enumerations and assign multiple values of the HabitableEnum to a planet?

Lets modify the enumeration to use the Flags attribute:

[Flags]
public enum HabitableEnum : byte
{
  Humanoids = 0x1,
  Insects = 0x2,
  Droids = 0x4,
  None = 0x8
}

We need to change the type of the ‘Habitable’ column in the database to a tinyint and we need to modify the information in the conceptual schema to inform the entity framework of our change in design:

image

The screenshot shows that we need to change the underlying type as well as check the “Set Flags attribute”.

We can now write code that assigns multiple values to the habitable field:

using ( var ctx = new StarWarsEntities() )
{
HabitableEnum x = HabitableEnum.Humanoids;
x |= HabitableEnum.Insects;
 
Planet p1 = new Planet() { Name = "Tatooine", Habitable = HabitableEnum.Droids };
Planet p2 = new Planet() { Name = "Coruscant", Habitable = x };
 
ctx.Planets.Add( p1 );
ctx.Planets.Add( p2 );
 
ctx.SaveChanges();
 
var query = from p in ctx.Planets
            select p;
 
foreach ( var p in query )
{
  Console.WriteLine( p.Name + " - " + p.Habitable );
}
 
Console.ReadLine();
}

The output looks like this:

image

If you wish to query for just insects you need to write a bitwise AND statement, like:

var query = from p in ctx.Planets
            where ( p.Habitable & HabitableEnum.Insects ) == HabitableEnum.Insects
            select p;

That’s all folks, have fun!

#    Comments [2] |