EntityFrameworkCore 有没有一种方法可以创建 EnumToStringConverter 而无需将枚举类型作为通用类型传递?
EntityFrameworkCore is there a way to create EnumToStringConverter without passing the enum type as generic?
我正在尝试使用 EntityFrameworkCore
ORM 与我的数据库进行交互。默认情况下,EntityFrameworkCore
似乎将枚举存储为 int 而不是字符串。
但是,我想将该值作为字符串存储在数据库中。我可以看到 EntityFrameworkCore
附带一个名为 EnumToStringConverter.
的转换器
我正在尝试使用反射来设置模型构建器,这样我就不必手动构建每个模型。
我 运行 遇到的问题是 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;
}
}
}
}
以上代码的唯一问题是 EnumToStringConverter 的构造方式。如果我能以某种方式向 EnumToStringConverter
的构造函数提供 Type
而不是将其作为解决问题的通用参数传递。
如 Pre-defined conversions 文档部分所述:
For common conversions for which a built-in converter exists there is no need to specify the converter explicitly. Instead, just configure which provider type should be used and EF will automatically use the appropriate build-in converter. Enum to string conversions are used as an example above, but EF will actually do this automatically if the provider type is configured:
后面有一个例子。
之后,您可以简单地使用:
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;
}
正在搜索相同的内容,但不想使用流畅的方法。
请将以下内容添加到您的枚举中 属性。
[Column(TypeName = "nvarchar(32)")]
这会自动将其保存为字符串。如果放置在基础 class 中,这适用于所有派生实体。
你也可以注册一个类型配置
public class BaseEntityTypeConfiguration : IEntityTypeConfiguration<BaseEntity>
{
public void Configure(EntityTypeBuilder<BaseEntity> builder)
{
builder.Property(p => p.YourEnumProp).HasConversion<string>();
}
}
然后你在modelBuilder上注册它
mb.ApplyConfiguration(new BaseEntityTypeConfiguration());
从 EF 核心 v6.0.0-preview6
开始,有一个更优雅的解决方案来全局注册一个 ValueConverter。由于 EFcore 已经附带 EnumToStringConverter
,只需将这些行添加到您的 DbContext
class:
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
// Instead of numeric conversion that EFcore uses by default
configurationBuilder.Properties<Enum>().HaveConversion<string>();
}
并且 Enum
类型的所有属性都将序列化为字符串,而不是数字。
我正在尝试使用 EntityFrameworkCore
ORM 与我的数据库进行交互。默认情况下,EntityFrameworkCore
似乎将枚举存储为 int 而不是字符串。
但是,我想将该值作为字符串存储在数据库中。我可以看到 EntityFrameworkCore
附带一个名为 EnumToStringConverter.
我正在尝试使用反射来设置模型构建器,这样我就不必手动构建每个模型。
我 运行 遇到的问题是 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;
}
}
}
}
以上代码的唯一问题是 EnumToStringConverter 的构造方式。如果我能以某种方式向 EnumToStringConverter
的构造函数提供 Type
而不是将其作为解决问题的通用参数传递。
如 Pre-defined conversions 文档部分所述:
For common conversions for which a built-in converter exists there is no need to specify the converter explicitly. Instead, just configure which provider type should be used and EF will automatically use the appropriate build-in converter. Enum to string conversions are used as an example above, but EF will actually do this automatically if the provider type is configured:
后面有一个例子。
之后,您可以简单地使用:
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;
}
正在搜索相同的内容,但不想使用流畅的方法。
请将以下内容添加到您的枚举中 属性。
[Column(TypeName = "nvarchar(32)")]
这会自动将其保存为字符串。如果放置在基础 class 中,这适用于所有派生实体。
你也可以注册一个类型配置
public class BaseEntityTypeConfiguration : IEntityTypeConfiguration<BaseEntity>
{
public void Configure(EntityTypeBuilder<BaseEntity> builder)
{
builder.Property(p => p.YourEnumProp).HasConversion<string>();
}
}
然后你在modelBuilder上注册它
mb.ApplyConfiguration(new BaseEntityTypeConfiguration());
从 EF 核心 v6.0.0-preview6
开始,有一个更优雅的解决方案来全局注册一个 ValueConverter。由于 EFcore 已经附带 EnumToStringConverter
,只需将这些行添加到您的 DbContext
class:
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
// Instead of numeric conversion that EFcore uses by default
configurationBuilder.Properties<Enum>().HaveConversion<string>();
}
并且 Enum
类型的所有属性都将序列化为字符串,而不是数字。