C# EntityFrameworkCore是否有方法创建EnumToStringConverter而不将枚举类型作为泛型传递?

C# EntityFrameworkCore是否有方法创建EnumToStringConverter而不将枚举类型作为泛型传递?,c#,reflection,entity,entity-framework-core,valueconverter,C#,Reflection,Entity,Entity Framework Core,Valueconverter,我正在尝试使用EntityFrameworkCoreORM与我的数据库交互。默认情况下,EntityFrameworkCore似乎将枚举存储为int而不是string 但是,我希望将该值作为字符串存储在数据库中。我可以看到EntityFrameworkCore附带了一个名为的转换器 我正在尝试使用反射来设置模型生成器,这样就不必手动构建每个模型 我遇到的问题是EnumToStringConverter接受的泛型类型必须是enum。但由于我试图在这里使用反射,因此在创建转换器时无法传递枚举类型 到

我正在尝试使用
EntityFrameworkCore
ORM与我的数据库交互。默认情况下,
EntityFrameworkCore
似乎将枚举存储为int而不是string

但是,我希望将该值作为字符串存储在数据库中。我可以看到
EntityFrameworkCore
附带了一个名为的转换器

我正在尝试使用反射来设置模型生成器,这样就不必手动构建每个模型

我遇到的问题是
EnumToStringConverter
接受的泛型类型必须是
enum
。但由于我试图在这里使用反射,因此在创建转换器时无法传递枚举类型

到目前为止,我的代码是这样的

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    // Get all DbSet<> properties that are defined in the DbContext
    var modelTypes = typeof(DataContext).GetProperties()
                                        .Where(x => x.PropertyType.IsGenericType && x.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>))
                                        .Select(x => x.PropertyType.GetGenericArguments().First())
                                        .ToList();

    foreach (Type modelType in modelTypes)
    {
        var properties = modelType.GetProperties();

        foreach (var property in properties)
        {
            if (IsPrimaryKey(property))
            {
                // At this point we know that the property is a primary key
                modelBuilder.Entity(modelType)
                            .Property(property.Name)
                            .UseSqlServerIdentityColumn()
                            .Metadata.BeforeSaveBehavior = PropertySaveBehavior.Ignore;

                continue;
            }

            if (property.PropertyType.IsEnum)
            {
                // At this point we know that the property is an enum.
                // Add the EnumToStringConverter converter to the property so that
                // the value is stored in the database as a string instead of number 
                var converter = new EnumToStringConverter(); // if somehow I can change this code to something like var `new EnumToStringConverter(property.PropertyType);` the code would work

                modelBuilder.Entity(modelType)
                            .Property(property.Name)
                            .HasConversion(converter);

                continue;
            }

        }
    }
}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
基于模型创建(modelBuilder);
//获取在DbContext中定义的所有DbSet属性
var modelTypes=typeof(DataContext).GetProperties()
.Where(x=>x.PropertyType.IsGenericType&&x.PropertyType.GetGenericTypeDefinition()==typeof(DbSet))
.Select(x=>x.PropertyType.GetGenericArguments().First())
.ToList();
foreach(modelTypes中的modelType类型)
{
var properties=modelType.GetProperties();
foreach(属性中的var属性)
{
if(IsPrimaryKey(属性))
{
//此时,我们知道该属性是主键
modelBuilder.Entity(modelType)
.Property(Property.Name)
.UseSqlServerIdentityColumn()
.Metadata.beforeSavebhavior=PropertySaveBhavior.Ignore;
继续;
}
if(property.PropertyType.IsEnum)
{
//此时,我们知道该属性是一个枚举。
//将EnumToStringConverter转换器添加到属性,以便
//该值作为字符串而不是数字存储在数据库中
var converter=new EnumToStringConverter();//如果我能以某种方式将此代码更改为var`new EnumToStringConverter(property.PropertyType);`代码将正常工作
modelBuilder.Entity(modelType)
.Property(Property.Name)
.转换(转换器);
继续;
}
}
}
}
上述代码的唯一问题是如何构造。如果我能以某种方式向
枚举字符串转换器的构造函数提供
类型
,而不是将其作为解决问题的通用参数传递。

如文档部分所述:

对于存在内置转换器的常见转换,无需显式指定转换器。相反,只需配置应使用的提供程序类型,EF就会自动使用适当的内置转换器。上面的示例使用枚举到字符串的转换,但如果配置了提供程序类型,EF实际上会自动执行此操作:

然后是一个例子

接下来,您可以简单地使用:

if (property.PropertyType.IsEnum)
{
    // At this point we know that the property is an enum.
    // Add the EnumToStringConverter converter to the property so that
    // the value is stored in the database as a string instead of number 
    modelBuilder.Entity(modelType)
        .Property(property.Name)
        .HasConversion<string>(); // <--

    continue;
}
if(property.PropertyType.IsEnum)
{
//此时,我们知道该属性是一个枚举。
//将EnumToStringConverter转换器添加到属性,以便
//该值作为字符串而不是数字存储在数据库中
modelBuilder.Entity(modelType)
.Property(Property.Name)

.HasConversion();//正在搜索相同的内容,但不想使用fluent方法

请将以下内容应用于您的枚举属性

 [Column(TypeName = "nvarchar(32)")] 
这将自动将其保存为字符串。如果放置在基类中,则适用于所有派生实体

您还可以注册类型配置

public class BaseEntityTypeConfiguration : IEntityTypeConfiguration<BaseEntity>
{
    public void Configure(EntityTypeBuilder<BaseEntity> builder)
    {
        builder.Property(p => p.YourEnumProp).HasConversion<string>();
    }
}

就是这样。我错过了默认情况下该怎么做,这样你就不必写200次了?@JeremyHolovacs你可以这样做:从这里用答案更改代码的内部部分。但是如果你在单独的so问题中问这个问题,我很乐意给你精确的答案!或者作为属性位置[Column(TypeName=“nvarchar(32)”)]到枚举属性。这将自动将其保存为字符串。
mb.ApplyConfiguration(new BaseEntityTypeConfiguration());