EF Core 2.0 枚举存储为字符串

EF Core 2.0 Enums stored as string

我能够将枚举作为字符串存储在数据库中。

builder.Entity<Company>(eb =>
{
    eb.Property(b => b.Stage).HasColumnType("varchar(20)");
});

但是当需要查询时,EF 不知道将字符串解析为枚举。我怎样才能这样查询:

context
    .Company
        .Where(x => x.Stage == stage)

这是异常:将 varchar 值 'Opportunity' 转换为数据类型 int

时转换失败

这与在以下位置回答的问题相同: Does EF7 support enums?

值转换功能是 EF Core 2.1 中的新增功能。

Value converters allow property values to be converted when reading from or writing to the database. This conversion can be from one value to another of the same type (for example, encrypting strings) or from a value of one type to a value of another type (for example, converting enum values to and from strings in the database.)

public class Rider
{
    public int Id { get; set; }
    public EquineBeast Mount { get; set; }
}

public enum EquineBeast
{
    Donkey,
    Mule,
    Horse,
    Unicorn
}

您可以使用自己的转换

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<Rider>()
        .Property(e => e.Mount)
        .HasConversion(
            v => v.ToString(),
            v => (EquineBeast)Enum.Parse(typeof(EquineBeast), v));
}

或内置转换器

var converter = new EnumToStringConverter<EquineBeast>();

modelBuilder
    .Entity<Rider>()
    .Property(e => e.Mount)
    .HasConversion(converter);

您可以使用它将所有实体的所有属性的所有枚举转换为字符串,反之亦然:

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using System;

namespace MyApp
{
    public class DatabaseContext : DbContext
    {
        public DbSet<UserContext> Users { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            // Configure your model here
        }

        protected override void OnModelCreating(ModelBuilder model)
        {
            foreach (var entityType in model.Model.GetEntityTypes())
            {
                foreach (var property in entityType.GetProperties())
                {
                    if (property.ClrType.BaseType == typeof(Enum))
                    {
                        var type = typeof(EnumToStringConverter<>).MakeGenericType(property.ClrType);
                        var converter = Activator.CreateInstance(type, new ConverterMappingHints()) as ValueConverter;

                        property.SetValueConverter(converter);
                    }
                }
            }
        }
    }
}