EntityFrameworkCore есть ли способ создать EnumToStringConverter, не передавая тип enum как универсальный?
Я пытаюсь использовать EntityFrameworkCore
ORM для взаимодействия с моими базами данных. По умолчанию, EntityFrameworkCore
похоже, что enum хранится как int вместо string.
Тем не менее, я хотел бы сохранить значение в базе данных в виде строки. я могу увидеть это EntityFrameworkCore
поставляется с конвертером EnumToStringConverter.
Я пытаюсь использовать отражение для настройки построителя модели, поэтому мне не нужно вручную строить каждую модель.
Проблема, с которой я сталкиваюсь, заключается в том, что EnumToStringConverter
принимает общий тип, который должен быть enum
, Но так как я пытаюсь использовать отражение здесь, я не могу передать тип 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. Если как-то я могу предоставить Type
конструктору EnumToStringConverter
вместо того, чтобы передавать его как общий аргумент, который решит проблему.
3 ответа
Как объясняется в разделе "Документация по предварительно определенным преобразованиям ":
Для обычных преобразований, для которых существует встроенный преобразователь, нет необходимости указывать преобразователь явно. Вместо этого просто укажите, какой тип поставщика следует использовать, и 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;
}
Начиная с ядра EF
v6.0.0-preview6
, существует более элегантное решение для глобальной регистрации ValueConverter. Поскольку EFcore уже поставляется с
EnumToStringConverter
, просто добавьте эти строки в свой
DbContext
учебный класс:
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
// Instead of numeric conversion that EFcore uses by default
configurationBuilder.Properties<Enum>().HaveConversion<string>();
}
и все свойства типа
Enum
будут сериализованы как строки, а не числа.
Искал то же самое, но не хотел использовать беглый подход.
поместите следующее в свойство перечисления.
[Column(TypeName = "nvarchar(32)")]
это автоматически сохранит его как строку. если он помещен в базовый класс, это относится ко всем производным объектам.
вы также можете зарегистрировать конфигурацию типа
public class BaseEntityTypeConfiguration : IEntityTypeConfiguration<BaseEntity>
{
public void Configure(EntityTypeBuilder<BaseEntity> builder)
{
builder.Property(p => p.YourEnumProp).HasConversion<string>();
}
}
затем вы регистрируете его на modelBuilder
mb.ApplyConfiguration(new BaseEntityTypeConfiguration());