Это пример приложения, которое я придумал, которое производит то же поведение, что и мое реальное гораздо более сложное приложение. Я, очевидно, пропустил какой-то конфигурационный аспект, но не могу понять, что это за жизнь. По какой-то причине каждая коллекция в моем классе KID получает свое собственное поле и внешний ключ в таблице Sweet .... что просто не нужно, насколько я могу видеть .....? Как я могу остановить создание EF?EF5 TPH Дополнительные внешние ключи генерируются - Как избавиться от них?
Примеров классов, конфигурация и результирующий код миграции следующим образом (NB, если я использую TPT вместо ТРНА дополнительных поля не добавляются и OwnerId используются в качестве реляционного поля просто отлично)
Моих классов:
public class Sweet
{
[Key]
public int SweetId { get; set; }
public string SweetName { get; set; }
[ForeignKey("OwnerId")]
public Kid Owner { get; set; }
public int OwnerId { get; set; }
}
public class Chocolate : Sweet {}
public class HardBoiled : Sweet {}
public class Chewy : Sweet {}
public class Kid
{
public int KidId { get; set; }
public string FirstName { get; set; }
public virtual ICollection<Chocolate> Chocolates { get; set; }
public virtual ICollection<HardBoiled> BaggedSweeets { get; set; }
public virtual ICollection<Chewy> PacketSweets { get; set; }
}
Моя конфигурация (Вызывается из OnModelCreating)
public class SweetConfiguration : EntityTypeConfiguration<Sweet>
{
public SweetConfiguration()
{
Map(m => m.ToTable("Sweet"));
Map<Chocolate>(i => i.Requires("SweetType").HasValue(1));
Map<Chewy>(i => i.Requires("SweetType").HasValue(2));
Map<HardBoiled>(f => f.Requires("SweetType").HasValue(3));
}
}
сгенерированный код миграции:
public override void Up()
{
CreateTable(
"dbo.Kid",
c => new
{
KidId = c.Int(nullable: false, identity: true),
FirstName = c.String(),
})
.PrimaryKey(t => t.KidId);
CreateTable(
"dbo.Sweet",
c => new
{
SweetId = c.Int(nullable: false, identity: true),
SweetName = c.String(),
OwnerId = c.Int(nullable: false),
Kid_KidId = c.Int(), <--- DON'T NEED THIS
Kid_KidId1 = c.Int(), <--- OR THIS
Kid_KidId2 = c.Int(), <-- OR THIS!
SweetType = c.Int(),
})
.PrimaryKey(t => t.SweetId)
.ForeignKey("dbo.Kid", t => t.Kid_KidId) <!-- LIKEWISE FOR THESE THREE KEYS
.ForeignKey("dbo.Kid", t => t.Kid_KidId1)
.ForeignKey("dbo.Kid", t => t.Kid_KidId2)
.ForeignKey("dbo.Kid", t => t.OwnerId, cascadeDelete: true)
.Index(t => t.Kid_KidId)
.Index(t => t.Kid_KidId1)
.Index(t => t.Kid_KidId2)
.Index(t => t.OwnerId);
}
UPDATE:
Как представляется моя текущая модель не поддерживается, я изменил свой класс Kid, как это:
public class Kid
{
public int KidId { get; set; }
public string FirstName { get; set; }
public virtual ICollection<Sweet> Sweets { get; set; }
[NotMapped]
public ICollection<HardBoiled> BaggedSweets
{
get
{
return Sweets.OfType<HardBoiled>().ToList();
}
}
... and two more read-only NotMapped properties for the other collections...
}
В моем фактическом коде Sweet - это абстрактный класс, поэтому я не использую его нигде - но я вижу вашу точку зрения о отсутствии наследования. Является ли эта проблема особой? Могут ли другие ОРМ справиться с этим типом модели? –
@DaveR: Я не знаю, могут ли другие ORM отображать эти классы, как вы хотите их сопоставить. По-моему, использование одной коллекции 'Sweets' не является большой потерей, потому что вы всегда можете фильтровать дочерние классы из коллекции. Если вы хотите, даже с тремя дополнительными (не отображаемыми) свойствами readonly (только с геттером) в 'Kid', которые возвращают' Sweets.OfType() 'as' IEnumerable 'и т. Д. –
Slauma
Да. Уже отредактировал мой ответ, чтобы показать, как я это сделал. Спасибо за разъяснения. –