【问题标题】:Foreign key constraint when there's a navigation property to a derived class派生类有导航属性时的外键约束
【发布时间】:2019-06-26 11:27:26
【问题描述】:

我使用代码优先在 Entity Framework 中创建我的数据库,并使用 Table per Hierarchy 方法为下面显示的类的继承层次结构。

当我运行迁移时,一切正常,但是当我更新我的数据库时,我收到以下错误:

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,我刚刚添加了以下内容以创建按预期工作的表(一个表中的所有属性都具有鉴别器列)。

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);

在更新数据库时,我还用一些测试数据播种它,我猜这是它发现这个问题的时候。

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

未来可能会有 BaseStatus 和 Rider 类的进一步派生类,不同的派生 Rider 使用不同的 Status 类,因此任何解决方案都必须具有可扩展性。可能是当项目增长时,我会从每个层次结构的表更改为每个类型的表,但现在我想要一个 TPH 的解决方案(如果可能的话)

【问题讨论】:

    标签: c# entity-framework inheritance


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      我终于找到答案了!!

      部分问题是我不知道要完成的任务的短语,因此很难找到答案。如果您想实现与我相同的目标,那么您需要的短语是多态关联。我终于在这篇文章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,您只需要添加数据注释以使实体创建单独的表。

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-03
        • 1970-01-01
        • 1970-01-01
        • 2011-08-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多