UPDATE: I found a better way that works well in EntityFrameworkCore 5.0.8
Add JsonConverter attributes to your enum
[Newtonsoft.Json.JsonConverter(typeof(StringEnumConverter))]
public enum FacultyEnum
{
[EnumMember(Value = "English Professor")]
Eng,
[EnumMember(Value = "Math Professor")]
Math,
[EnumMember(Value = "Economics Professor")]
Eco
}
Create a class the represents the table
public class Faculty
{
public int Id { get; set; }
public string Name { get; set; }
public FacultyEnum Description { get; set; }
}
Use Fluent API in OnModelCreating in your DbContext to use the enum strings and set check constraints
var enumToString = new EnumToStringConverter<FacultyEnum>();
modelBuilder.Entity<Faculty>(entity =>
{
entity.ToTable(nameof(FacultyMembers));
//convert enums to string
entity.Property(e => e.Description).HasConversion(enumToString);
//build check constraint from enum
var allowedEnumStrings = string.Join(',',
typeof(Faculty).GetMembers()
.Select(x => x.GetCustomAttribute(typeof(EnumMemberAttribute), false)).Where(x => x != null)
.Select(x => $"'{((EnumMemberAttribute)x).Value}'"));
entity.HasCheckConstraint($"CK_{nameof(FacultyMembers)}_{nameof(Faculty.Description)}", $"{nameof(Faculty.Description)} in ({allowedEnumStrings})");
});
Old Way
Alberto Monteiro answered this very well. I had to make a few adjustments to get it to work with EF core.
Rename your enum and add description decorators
public enum FacultyEnum
{
[Description("English Professor")]
Eng,
[Description("Math Professor")]
Math,
[Description("Economics Professor")]
Eco
}
Create a class that represent the table
public class Faculty
{
private Faculty(FacultyEnum @enum)
{
Id = (int)@enum;
Name = @enum.ToString();
Description = @enum.GetEnumDescription();
}
protected Faculty() { } //For EF
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
[Required, MaxLength(100)]
public string Name { get; set; }
[MaxLength(100)]
public string Description { get; set; }
public static implicit operator Faculty(FacultyEnum @enum) => new Faculty(@enum);
public static implicit operator FacultyEnum(Faculty faculty) => (FacultyEnum)faculty.Id;
}
Your model reference the class
public class ExampleClass
{
public virtual Faculty Faculty { get; set; }
}
Create a extension method to get description from enum and seed values
using System;
using System.ComponentModel;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq;
public static class Extensions
{
public static string GetEnumDescription<TEnum>(this TEnum item)
=> item.GetType()
.GetField(item.ToString())
.GetCustomAttributes(typeof(DescriptionAttribute), false)
.Cast<DescriptionAttribute>()
.FirstOrDefault()?.Description ?? string.Empty;
}
Add the seed in YourDbContext.cs
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Faculty>().HasData(FacultyEnum.Eng, FacultyEnum.Math, FacultyEnum.Eco);
}
Add the enum table in your DbContext
public class MyClass : DbContext
{
public DbSet<ExampleClass> Examples { get; set; }
public DbSet<Faculty> Facultys { get; set; }
}
Use it
var example = new ExampleClass();
example.Faculty = FacultyEnum.Eng;
if (example.Faculty == FacultyEnum.Math)
{
//code
}
To remember
If you don't add virtual in Faculty property, you must use Include method from DbSet to do Eager Load
var exampleFromDb = dbContext.Examples.Include(x => x.Faculty).SingleOrDefault(e => e.Id == 1);
if (example.Faculty == FacultyEnum.Math)
{
//code
}
If Faculty property is virtual, then just use it
var exampleFromDb = dbContext.Examples.Find(1);
if (example.Faculty == FacultyEnum.Math)
{
//code
}