Управление сопоставлением столбцов с пользовательским соглашением в Entity Framework 6

У меня есть класс TypeEntity, который будет действовать как базовый класс для нескольких десятков объектов. Я использую TPC, поэтому мне нужно сопоставить все свойства базового класса с таблицей с именем конкретного класса и установить поле Key для создания базы данных.

В настоящее время я делаю это с EntityTypeConfiguration для каждого типа сущности, который выглядит следующим образом:

class LineItemType : EntityTypeConfiguration<Models.LineItemType>
{
    public LineItemType()
    {
        this.Property(e => e.Key)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        this.Map(e => e.MapInheritedProperties()
                       .ToTable(nameof(LineItemType)));
    }
}

Это прекрасно работает, но очень повторяется. Я должен помнить о создании класса конфигурации для каждого типа, который наследует от TypeEntity, устанавливает ключ и сопоставляет унаследованные свойства. Это кажется идеальным вариантом для пользовательского Convention.


Я создал TypeEntityTpcConvention Convention следующим образом:

class TypeEntityTpcConvention : Convention
{
    public TypeEntityTpcConvention()
    {
        this.Types<TypeEntity>()
            .Configure(e => e.Property(p => p.Key)
                             .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity));
    }
}

Что работает, чтобы установить Key как сгенерированную базу данных, но я не могу найти способ доступа к сопоставлениям таблиц для свойств изнутри соглашения.


В идеале я ожидал бы что-то вроде этого:

this.Types<TypeEntity>()
    .Configure(e => e.MapInheritedProperties()
    .ToTable(e.ClrType.Name));

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

this.Types<TypeEntity>()
    .Configure(e => e.Property(p=>p.Key)
                     .ToTable(e.ClrType.Name));

Ни один из них не существует. Есть ли способ управлять отображением свойств изнутри a Convention?


После некоторых дополнительных исследований, похоже, что в качестве IStoreModelConvention и IConceptualModelConvention доступны более расширенные варианты условных соглашений, но полезной документации по их использованию не хватает. Через несколько часов, пробивая через них точки останова и окна просмотра, я не понял, как управлять сопоставлением столбцов с помощью этих интерфейсов.


Мое текущее решение - использовать отражение, чтобы найти все типы, наследующие от TypeEntity в OnModelCreating, и сопоставить свойства с правильной таблицей. Это работает, но я предпочел бы использовать соглашение, если это возможно, поскольку это действительно похоже на то, для чего были сделаны условные обозначения. Я чувствую, что мне не хватает чего-то очевидного.

Ответ 1

Насколько я могу судить, вы можете просто написать конфигурацию типа в методе OnModelCreating вашего DbContext и он очень похож на код, который вы уже упомянули в вопросе.

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

    modelBuilder.Types<TypeEntity>().Configure(c =>
    {
        c.HasKey(p => p.Key);
        // probably not needed, but won't do any harm
        c.Property(p => p.Key).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        c.ToTable(c.ClrType.Name);
    });
}

Если у вас есть какие-либо проблемы с этим подходом, сообщите мне, и я перейду на эту тему.

Edit:

Тот же самый принцип может применяться с условностями:

class TypeEntityConvention : Convention
{
    public TypeEntityConvention()
    {
        this.Types<TypeEntity>().Configure(c =>
        {
            c.HasKey(p => p.Key);
            c.Property(p => p.Key).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            c.ToTable(c.ClrType.Name);
        });
    }
}

и

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

    modelBuilder.Conventions.Add<TypeEntityConvention>();
}