EF Core 2.0枚举存储为字符串

Bra*_*ets 10 entity-framework ef-core-2.0

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

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

但是,当需要查询时,EF不知道将字符串解析为枚举.我该如何查询:

context
    .Company
        .Where(x => x.Stage == stage)
Run Code Online (Sandbox Code Playgroud)

这是一个例外:将varchar值'Opportunity'转换为数据类型int时转换失败

小智 29

Value Conversions功能是EF Core 2.1中的新功能.

值转换器允许在读取或写入数据库时​​转换属性值.此转换可以是相同类型的一个值(例如,加密字符串),也可以是一种类型的值转换为另一种类型的值(例如,将枚举值转换为数据库中的字符串.)

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

public enum EquineBeast
{
    Donkey,
    Mule,
    Horse,
    Unicorn
}
Run Code Online (Sandbox Code Playgroud)

您可以使用自己的转换

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

或内置转换器

var converter = new EnumToStringConverter<EquineBeast>();

modelBuilder
    .Entity<Rider>()
    .Property(e => e.Mount)
    .HasConversion(converter);
Run Code Online (Sandbox Code Playgroud)

  • 这可以通过属性来实现稍微简单一些,只需将相应的列标记为“nvarchar”即可。[参见此处](https://learn.microsoft.com/en-us/ef/core/modeling/value-conversions#pre-defined-conversions) (3认同)

ped*_*del 7

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

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);
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,此代码不适用于可为空的枚举属性。要支持这些,请使用相同的代码添加“else if (Nullable.GetUnderlyingType(property.ClrType)?.IsEnum == true)”,但将“Nullable.GetUnderlyingType(property.ClrType)!”传递给“MakeGenericType()” 。 (5认同)
  • 我们可以使用方便的属性“property.ClrType.IsEnum”,而不是检查“property.ClrType.BaseType == typeof(Enum)” (3认同)