How to create a table corresponding to enum in EF6 Code First?

前端 未结 8 1552
失恋的感觉
失恋的感觉 2020-11-29 17:10

I\'ve followed MSDN on how to handle enumerations in Code First for EF6. It worked, as supposed to but the field in the created table that refers to the enu

相关标签:
8条回答
  • 2020-11-29 17:58

    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
    }
    
    0 讨论(0)
  • 2020-11-29 18:07

    I might be a bit late for the party but I didn't find the answer I was looking for here.

    While looking around in the EntityFramework documentation I found the solution, it is the first example in Value Conversions

    With this you can make a nice extension method if you want. i.e.

    public static void HasEnum<TEntity, TProperty>(this EntityTypeBuilder<TEntity> entityBuilder, Expression<Func<TEntity, TProperty>> propertyExpression)
            where TEntity : class
            where TProperty : Enum
        {
            entityBuilder.Property(propertyExpression)
                .HasConversion(
                    v => v.ToString(),
                    v => (TProperty)Enum.Parse(typeof(TProperty), v)
                );
        }
    

    Then use it in your OnModelCreating:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<YourEntity>()
            .HasEnum(e => e.YourProperty);
    }
    
    0 讨论(0)
提交回复
热议问题