1

这是我制作的示例应用程序,它产生与我的实际更复杂的应用程序相同的行为。 我很明显在某处丢失了一些配置方面,但无法弄清楚我的生活。出于某种原因,我的KID类中的每个集合都在Sweet table中接收它自己的字段和外键....只要我不能看到....., 如何阻止EF生成这些?EF5 TPH正在生成额外的外键 - 如何摆脱它们?

实施例类,配置和所得迁移代码如下(NB,如果我使用TPT代替TPH的额外字段不添加和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:

因为这似乎是不支持我目前的模型我已经改变了我的孩子类是这样的:

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属性(OwnerOwnerId)的在集合指的类声明直接(即在ChocolateHardBoiledChewy)在基类和不。为了使它工作,只有一个外键,你只能在Kid是指基类中定义一个导航集合,其中OwnerOwnerId中宣称:

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

(您可以顺便说一句提取特定类型的此集合使用Sweets.OfType<Chocolate>()等)

这也是TPT的情况。您的TPT测试中是否可能没有SweetConfigurationDbSet<Sweet>?这会导致模型根本没有继承(来自EF视角),因为基类Sweet的所有属性都将被添加到三个子表中。

+0

在我的实际代码中,Sweet是一个抽象类,所以我没有在任何地方使用它 - 但是我看到了你的观点,即没有继承。 这个问题EF具体吗?其他ORM可以应付这种类型的模型吗? –

+0

@DaveR:我不知道其他ORM是否可以映射这些类,就像你想映射它们一样。在我看来,使用单个“Sweets”集合并不是一个很大的损失,因为您始终可以将子类从集合中筛选出来。如果你想在'Kid'中添加三个额外的(未映射的)只读属性(只有一个getter),那么返回'Sweets.OfType ()'为'IEnumerable '等 – Slauma

+0

是的。已经编辑我的答案,以显示我是如何做到这一点的。感谢澄清。 –

相关问题