Подтвердить что ты не робот

Можно ли указать столбец дискриминатора с отображением таблицы на тип?

У меня есть иерархия классов, которую я хочу сопоставить в нескольких таблицах, используя Entity Framework 4.1 Code First. Он похож на таблицу на тип (TPT), но мне также нужен столбец дискриминатора.

Иерархия выглядит примерно так:

public class Event
{
    public Guid Id { get; set; }
    public string Code { get; set; } // discriminator
    public DateTime Date { get; set; }
}

public class Party : Event
{
    public int AttendeeCount { get; set; }
}

public class BirthdayParty : Party
{
    public int Age { get; set; }
}

public class WeddingParty : Party
{
    public string Surname { get; set; }
}

Это довольно слабый пример, но я надеюсь, что это имеет смысл. Будет таблица "События", таблица "Стороны" и таблица для каждого типа вечеринки. Однако столбец дискриминатора ( "Код" ) будет иметь известное значение для каждого вида событий, например "BIRTH" для дней рождения или "WEDDING" для свадебных вечеринок.

Идея состоит в том, что если я запрошу только дни рождения на определенную дату, EF будет знать, чтобы добавить Code = 'BIRTH' в мой запрос вместо того, чтобы делать кучу UNION и JOINs, чтобы определить, какие строки ему нужны.

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

var bd = modelBuilder.Entity<BirthdayParty>();
bd.ToTable("BirthdayParties");
bd.Property(p => p.Age).HasColumnName("BirthdayAge");

Теперь мне нужно как-то указать значение дискриминатора. Я пробовал это:

modelBuilder.Entity<Event>().Map<BirthdayParty>(cfg =>
    {
        cfg.Requires("Code").HasValue("BIRTH");
    });

... но жалуется, что я не указал имя таблицы внутри вызова Map. Поэтому я попытался перевести вызов ToTable туда:

var bd = modelBuilder.Entity<BirthdayParty>();
bd.Property(p => p.Age).HasColumnName("BirthdayAge");

modelBuilder.Entity<Event>().Map<BirthdayParty>(cfg =>
    {
        cfg.Requires("Code").HasValue("BIRTH");
        cfg.ToTable("BirthdayParties");
    });

... и теперь он думает, что мне нужен столбец "Code" в таблице "BirthdayParties", что неверно. Я уже сказал, что столбец "Код" находится в таблице "События".

Возможно ли это? Могу ли я объединить использование столбца дискриминатора с отображением таблицы на тип?

4b9b3361

Ответ 1

К сожалению, это не поддерживается. Столбец дискриминатора может использоваться только в TPH. TPT различает типы сущностей по отображаемым таблицам и всегда производит эти ужасные запросы. Это может быть приятной особенностью, поэтому возможно предложение Data UserVoice сделало бы его осуществленным в один прекрасный день.

Обновление

Уже есть предложение по голосованию пользователя для этой подписи " Поддержка столбца дискриминатора в наследовании TPT".

Ответ 2

Я сделал переопределение на SaveChanges, чтобы выполнить что-то подобное. Я просто добавил атрибут в абстрактный класс под названием Descriminator и установил его на основе имени класса Concrete в любое время, когда добавилось что-то новое.

public class MyContext : DbContext
{        
    public override int SaveChanges()
    {
        foreach (var item in ChangeTracker.Entries().Where(x=>x.Entity is MyAbstractClass && x.State == EntityState.Added))
        {
            ((MyAbstractClass)item.Entity).Descriminator = item.Entity.GetType().Name;
        }
        return base.SaveChanges();
    }
}