EntityFrameworkCore есть ли способ создать EnumToStringConverter без передачи типа перечисления как универсального?

Я пытаюсь использовать ORM EntityFrameworkCore для взаимодействия с моими базами данных. По умолчанию EntityFrameworkCore хранит enum как 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. Если каким-то образом я могу предоставить Type конструктору EnumToStringConverter вместо того, чтобы передавать его как общий аргумент, который решит проблему.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
0
2 802
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Как объяснено в разделе документации Предопределенные преобразования:

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;
}

Это сработало. я скучаю по этому

Junior 15.06.2018 20:00

Как это сделать по умолчанию, чтобы не пришлось 200 раз писать?

Jeremy Holovacs 22.02.2019 02:12

@JeremyHolovacs, вы можете сделать это так: stackoverflow.com/questions/50727860/… просто измените внутреннюю часть кода с ответом отсюда. Но если вы зададите это в отдельном SO-вопросе, я буду рад дать вам точный ответ!

Dominik 08.04.2019 21:33

или в качестве атрибута поместите [Column (TypeName = "nvarchar (32)")] в свойство enum. это автоматически сохранит его как строку.

Sven Krauter 20.04.2020 13:22

искал то же самое, но не хотел использовать беглый подход.

поместите следующее в свое свойство 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());

Другие вопросы по теме