我正在使用代码优先的方法在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解决方案(如果可能)
答案 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);