1

Это пример приложения, которое я придумал, которое производит то же поведение, что и мое реальное гораздо более сложное приложение. Я, очевидно, пропустил какой-то конфигурационный аспект, но не могу понять, что это за жизнь. По какой-то причине каждая коллекция в моем классе 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... 
} 

ответ

1

Вы не можете использовать три коллекции в этой модели. EF ожидает, что обратное свойство и свойство FK (Owner и OwnerId) являются объявлены непосредственно в классах коллекции отсылая к (т.е. в Chocolate, HardBoiled и Chewy), а не в базовом классе. Для того, чтобы сделать его работу и имеют только один внешний ключ можно определить только одну коллекцию навигации в Kid, который ссылается на базовый класс, где Owner и OwnerId объявлены в:

public class Kid 
{ 
    public int KidId { get; set; } 
    public string FirstName { get; set; } 
    public virtual ICollection<Sweet> Sweets { get; set; } 
} 

(Вы можете кстати извлечь определенные типы из этот сбор с использованием Sweets.OfType<Chocolate>() и т. д.)

Это также относится к TPT. Возможно ли, что у вас не было SweetConfiguration и нет DbSet<Sweet> в вашем тесте TPT? Это приведет к модели без наследования вообще (с точки зрения EF), потому что все свойства базового класса Sweet были бы добавлены в три дочерние таблицы.

+0

В моем фактическом коде Sweet - это абстрактный класс, поэтому я не использую его нигде - но я вижу вашу точку зрения о отсутствии наследования. Является ли эта проблема особой? Могут ли другие ОРМ справиться с этим типом модели? –

+0

@DaveR: Я не знаю, могут ли другие ORM отображать эти классы, как вы хотите их сопоставить. По-моему, использование одной коллекции 'Sweets' не является большой потерей, потому что вы всегда можете фильтровать дочерние классы из коллекции. Если вы хотите, даже с тремя дополнительными (не отображаемыми) свойствами readonly (только с геттером) в 'Kid', которые возвращают' Sweets.OfType () 'as' IEnumerable 'и т. Д. – Slauma

+0

Да. Уже отредактировал мой ответ, чтобы показать, как я это сделал. Спасибо за разъяснения. –

Смежные вопросы