Иметь определенную конфигурацию свойств для всех типов, реализующих интерфейс, за исключением одного

У меня есть несколько типов, которые наследуются от интерфейса «IEventReportElement», который предоставляет свойство «IdEventReport»:

public interface IEventReportElement
{
    long Id { get; set; }
    long? IdEventReport { get; set; }
}

Это свойство, допускающее значение NULL, так как я не всегда могу сразу правильно его заполнить, но оно не должно быть обнуляемым в базе данных.

Вот почему я добавил строку

modelBuilder.Types<IEventReportElement>().Configure(x=>x.Property(y=>y.IdEventReport).IsRequired());

к моему методу OnModelCreating в DbContext.

Однако тип «Позиция» должен реализовывать этот интерфейс, но НЕ должен иметь столбец для свойства «IdEventReport» в базе данных, а вместо этого должен иметь столбец для свойства «IdParent», которое он предоставляет.

public class Position : BOBase, IEventReportElement
{
    public long? IdEventReport 
    {
        get { return IdParent; }
        set { IdParent = value; }
    }

    public long? IdParent { get; set; }
}

и раздел в modelBuilder

        modelBuilder.Entity<Position>().Property(x => x.IdParent).IsRequired();
        modelBuilder.Entity<Position>().Ignore(x => x.IdEventReport);

Однако это вызывает исключение уже при попытке создать базу данных:

System.InvalidOperationException: свойство «IdEventReport» не является объявленным свойством типа «Позиция». Убедитесь, что свойство не было явно исключено из модели с помощью метода Ignore или аннотации данных NotMappedAttribute. Убедитесь, что это допустимое примитивное свойство.

Хотя это может быть допустимо, нельзя ли переопределить данную конфигурацию типа для определенного типа? Должен ли я добавлять строку .IsRequired() ко всем другим типам, реализующим этот интерфейс, или есть другой способ обойти это?


person DevilSuichiro    schedule 08.09.2016    source источник
comment
Я предполагаю, что вы пытаетесь выбрать Position.IdEventReport в запросе. это правильно?   -  person Adil Mammadov    schedule 08.09.2016
comment
нет, IdEventReport не должен быть включен в модель. IEventReportElement имеет другие важные свойства, которые я хочу использовать, я просто не хочу использовать это свойство (в базе данных).   -  person DevilSuichiro    schedule 08.09.2016


Ответы (2)


Я нашел решение, но оно не очень приятное. Я сделал это, изменив строку конфигурации типа на

modelBuilder.Types<IEventReportElement>().Where(x=>x.Name!="Position").Configure(x=>x.Property(y=>y.IdEventReport).IsRequired());
person DevilSuichiro    schedule 08.09.2016

Если вы просто хотите, чтобы столбец имел другое имя в базе данных, используйте HasColumnName.

Для доступа к IdParent в модели C# используйте [NotMapped], чтобы указать EF игнорировать это свойство при создании базы данных.

public class Position : BOBase, IEventReportElement {
    public long? IdEventReport {get; set; }

    [NotMapped]
    public long? IdParent {
        get { return IdEventReport ; }
        set { IdEventReport = value; }
    } 
}

modelBuilder.Entity<Position>().Property(x => x.IdEventReport).HasColumnName("IdParent");

В качестве примечания: почему вы реализуете интерфейс, который не хотите использовать? Возможно, вы можете разделить интерфейс на более мелкие части и реализовать только то, что собираетесь использовать.

person Georg Patscheider    schedule 08.09.2016
comment
Это не то, что я хочу, так как я хочу запросить таблицу по свойству IdParent, это невозможно при таком подходе. - person DevilSuichiro; 08.09.2016