Author : MD TAREQ HASSAN
Enum support in EF Core
- EF Core 2.1+ supports Enum
- Enum is supported via Value Conversions
- Enum type
- Enum type can be set easily in EDMX but EF Core does not support EDMX yet
- It’s easy to configure to use enum in Model First approach but difficult in Database First approach
- Links:
public enum Region : byte
{
[Description("Asia")]
Asia = 1,
[Description("Australia")]
Australia = 2,
[Description("Africa")]
Africa = 3,
[Description("America")]
America = 4,
[Description("Europe")]
Europe = 5
}
public class Employee
{
public int Id { get; set; }
// ... ... ...
public Region EmployedRegion { get; set; }
}
EmployeeDbContext.OnModelCreating(...)
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Employee>()
.Property(e => e.EmployedRegion)
.HasConversion(
v => v.ToString(),
v => (Region)Enum.Parse(typeof(Region), v));
}
Enum in Database First Approach
- Database column: use
nvarchar(n)
as column type - UI Model property: use Enum type
- Domain Model <-> UI Model: use AutoMapper to map domain model to/from UI model
- Disadvantage: if data in changed in master table, enum members must be changed accordingly
Explicitly using ValueConverter
EmployeeDbContext.OnModelCreating(...)
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var converter = new ValueConverter<Region, string>(
v => v.ToString(),
v => (Region)Enum.Parse(typeof(Region), v));
modelBuilder
.Entity<Employee>()
.Property(e => e.EmployedRegion)
.HasConversion(converter);
}
Using Built-in converters
- EF Core ships with a set of pre-defined ValueConverter classes
- https://docs.microsoft.com/en-us/ef/core/modeling/value-conversions#built-in-converters
EmployeeDbContext.OnModelCreating(...)
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var converter = new EnumToStringConverter<Region>();
modelBuilder
.Entity<Employee>()
.Property(e => e.EmployedRegion)
.HasConversion(converter);
}
When using built-in-converters, no need to specify the converter explicitly. So, the above can be simplified as below:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Employee>()
.Property(e => e.EmployedRegion)
.HasConversion<string>();
}
The same thing can be achieved by explicitly specifying the column type
public class Employee
{
public int Id { get; set; }
// ... ... ...
[Column(TypeName = "nvarchar(24)")]
public Region EmployedRegion { get; set; }
}