具有派生类的导航属性时的外键约束

时间:2019-06-26 11:27:26

标签: c# entity-framework inheritance

我正在使用代码优先的方法在Entity Framework中创建我的数据库,并正在使用“每个层次的表”方法来显示以下类的继承层次结构。

运行迁移时一切正常,但是更新数据库时出现以下错误:

  

System.Data.SqlClient.SqlException:INSERT语句与FOREIGN KEY约束“ FK_dbo.BaseStatus_dbo.Rider_ID”冲突。在数据库“ ASPNET_INSURANCE_c48b7267b7cd4bac952caa1a467ab9ae”的表“ dbo.Rider”的“ ID”列中发生了冲突。

我有一个具有对派生类的导航属性的类。 (简化代码)

    public class Rider
    {
       public int ID { get; set; }
       public virtual DerivedStatus derivedStatus { get; set; }
    }

带有数据注释的派生类如下:

    public class BaseStatus
    {
        [Key, ForeignKey("rider")]
        public int ID { get; set; }

        public bool? Married { get; set; }

        public virtual Rider rider { get; set; }
    }

    public class DerivedStatus : BaseStatus
    {
        public bool? HomeOwnership { get; set; }
    }

对于DbContext,我刚刚添加了以下内容来创建可以按预期工作的表(一个表中的所有属性都有Discriminator列)。

public DbSet<BaseStatus> Status { get; set; }

Rider与派生类之间的关系是一对一的。

我不确定它是否有用/有帮助,但下面是生成的DbMigration文件的一部分:

                CreateTable(
                "dbo.Rider",
                c => new
                    {
                        ID = c.Int(nullable: false, identity: true),
                        CorrelationID = c.Guid(),
                        derivedStatus_ID = c.Int(),
                    })
                .PrimaryKey(t => t.ID)
                .ForeignKey("dbo.BaseStatus", t => t.derivedStatus_ID)
                .Index(t => t.derivedStatus_ID);

在更新数据库时,我还为它添加了一些测试数据,我猜想是它解决了这个问题。

这是我第一次在Entity中使用继承,但我不确定问题出在哪里。我尝试删除数据库并重新运行迁移,因为我读到这有时可能会导致问题,但是我得到了相同的错误消息。

展望未来,可能还会有BaseStatus和Rider类的其他派生类,而不同的派生Riders使用不同的Status类,因此任何解决方案都必须是可扩展的。可能是随着项目的增长,我将从“按层次结构的表”更改为“按类型的表”,但是目前,我希望有一种TPH解决方案(如果可能)

2 个答案:

答案 0 :(得分:0)

检查表中的值,这些值是否有效(遵循外键约束)

答案 1 :(得分:0)

我终于找到答案了!!

问题的一部分是我不知道我要完成的工作,因此很难找到答案。如果您想实现与我相同的目标,则您需要的短语是 Polymorphic Associations 。我终于在本文here中找到了想要的东西。

要纠正我的代码,我要做的就是从依赖类中删除外键和导航属性,同时将导航属性保留在Rider中。

    public class Rider
    {
       public int ID { get; set; }
       public virtual DerivedStatus derivedStatus { get; set; }
    }

    public class BaseStatus
    {
        [Key]
        public int ID { get; set; }

        public bool? Married { get; set; }

    }

    public class DerivedStatus : BaseStatus
    {
        public bool? HomeOwnership { get; set; }
    }

DbContext与以前相同。经过测试,这也适用于TPT,您只需要添加数据注释即可使Entity创建单独的表。

更新:经过更多测试,我发现您可以在基类上使用外键和导航属性,但是您需要用Fluent API补充数据注释,因为我似乎无法使其正常工作它自己的。我使用的Fleunt API是:

modelBuilder.Entity<BaseStatus>()
                .HasRequired(e => e.Rider)
                .WithOptional(e => e.DerivedStatus)
                .WillCascadeOnDelete(true);