Saving Enums with Entity Framework Core

Full source code here.

A few years ago I wrote a post about saving enums to the database with Entity Framework. It was able to save the enum as a string to the database and when reading from the database it was able to take that string and populate the enum correctly. It worked fine but felt a bit hacky.

With Entity Framework Core there is a neater and nicer way to do this using value conversions.

Let’s say we have an Address with two enums - AddressType and DeliveryPreference.

1public partial class Address
3    public int AddressId { get; set; }
4    public string Line1 { get; set; }
5    public string Line2 { get; set; }
6    public AddressType AddressType { get; set; }
7    public DeliveryPreference DeliveryPreference { get; set; }

We can save the enums to the database as either strings or ints, and when reading them back populate the enum! Here’s how to do both.

The table

My table looks like this

As you can see, the AddressType is stored as an int and the DeliveryPreference is stored as a string.

When you run the application it should create the database and table for you, but in case you don’t have your permissions setup correctly, here’s the script to create it.

1CREATE TABLE [dbo].[Address] (
2    [AddressId]          INT            IDENTITY (1, 1) NOT NULL,
3    [Line1]              VARCHAR (50)   NOT NULL,
4    [Line2]              VARCHAR (50)   NOT NULL,
5    [AddressType]        INT            NOT NULL,
6    [DeliveryPreference] VARCHAR (50) NOT NULL,

Saving an enum as an string

Firstly lets look at saving the DeliveryPreference enum as an string.

In the context we build the entity, I have the usual things you would expect for AddressId, Line1 and Line2. But DeliveryPreference is a little different.

 1protected override void OnModelCreating(ModelBuilder modelBuilder)
 3    modelBuilder.Entity<Address>(entity =>
 4    {
 5        entity.Property(e => e.AddressId).ValueGeneratedOnAdd();
 7        entity.Property(e => e.Line1)
 8            .IsRequired()
 9            .HasMaxLength(50)
10            .IsUnicode(false);
12        entity.Property(e => e.Line2)
13            .IsRequired()
14            .HasMaxLength(50)
15            .IsUnicode(false);
17        entity.Property(e => e.DeliveryPreference) 
18            .HasMaxLength(50)
19            .HasConversion(x => x.ToString(), // to converter
20                x => (DeliveryPreference) Enum.Parse(typeof(DeliveryPreference), x));// from converter
22	    //snip..

The DeliveryPreference uses the HasConversion method, passing it two parameters. The first parameter is the convert to provider expression which as the name suggests converts the value in our object to the type you will store in the database.

And the second is the convert from provider expression, it converts the the type in database to the type in your class.

In this example, I cast the enum to an string to store in the database, and when retrieving from the database I cast the stored string to an DeliveryPreference enum.

Saving an enum as an int

For the second enum, AddressType I don’t explicitly need to convert it from an enum to an int, Entity Framework will do this automatically (as pointed out to me in this tweet). But I’m including it as an example in case you need something like this for some other explicit conversion.

In this example, I cast the enum to an int to store in the database, and when retrieving from the database I cast the stored int to an AddressType enum.

1// this is a continuation of the OnModelCreating method
2        entity.Property(e => e.AddressType)
3            .HasConversion(x => (int) x, x => (AddressType) x);

Full source code here.

comments powered by Disqus