Можно ли указать столбец дискриминатора с отображением таблицы на тип?
У меня есть иерархия классов, которую я хочу сопоставить в нескольких таблицах, используя 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", что неверно. Я уже сказал, что столбец "Код" находится в таблице "События".
Возможно ли это? Могу ли я объединить использование столбца дискриминатора с отображением таблицы на тип?
Ответы
Ответ 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();
}
}