正在生成EF5 TPH额外外键 - 如何摆脱它们?

时间:2013-10-02 18:36:11

标签: ef-code-first entity-framework-5 table-per-type table-per-hierarchy

这是我编写的示例应用程序,它产生与我实际的更复杂的应用程序相同的行为。 我显然在某个地方缺少一些配置方面,但无法弄明白我的生活。出于某种原因,我的KID类中的每个集合都在Sweet表中接收它自己的字段和外键....就我所见,这是不必要的.....? 如何阻止EF生成这些?

示例类,配置和生成的迁移代码如下(注意,如果我使用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);

    }

更新:

因为看起来我的当前模型不受支持,所以我改变了我的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 个答案:

答案 0 :(得分:1)

您不能在此模型中使用三个集合。 EF期望反向属性和FK属性(OwnerOwnerId)在集合引用的类中直接声明 (即Chocolate,{ {1}}和HardBoiled)而不是基类。要使其工作并且只有一个外键,您只能在Chewy中定义一个引用KidOwner的基类的单个导航集合:

OwnerId

(您可以使用public class Kid { public int KidId { get; set; } public string FirstName { get; set; } public virtual ICollection<Sweet> Sweets { get; set; } } 等从该集合中提取特定类型。)

TPT的情况也是如此。您的TPT测试中是否可能没有Sweets.OfType<Chocolate>()SweetConfiguration?这将导致模型完全没有继承(从EF视角),因为基类DbSet<Sweet>的所有属性都已添加到三个子表中。