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
2{
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; }
8}
We can save the enums to the database as either string
s or int
s, 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,
7 CONSTRAINT [PK_Address] PRIMARY KEY CLUSTERED ([AddressId] ASC)
8);
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)
2{
3 modelBuilder.Entity<Address>(entity =>
4 {
5 entity.Property(e => e.AddressId).ValueGeneratedOnAdd();
6
7 entity.Property(e => e.Line1)
8 .IsRequired()
9 .HasMaxLength(50)
10 .IsUnicode(false);
11
12 entity.Property(e => e.Line2)
13 .IsRequired()
14 .HasMaxLength(50)
15 .IsUnicode(false);
16
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
21
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.