我有一个PhoneNumber
实体,我想在多个实体中引用它。例如,有许多 PhoneNumbers的Contact
实体,以及一个 PhoneNumber的Business
实体。
public class PhoneNumber
{
[Key, Column(Order = 0), DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Number { get; set; }
}
public class Contact
{
[Key, Column(Order = 0), DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public virtual ICollection<PhoneNumber> PhoneNumbers { get; set; }
}
public class Business
{
[Key, Column(Order = 0), DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[ForeignKey("PhoneNumber")]
public int PhoneNumberId { get; set; }
public virtual PhoneNumber PhoneNumber { get; set; }
}
我已设置Contact
和Business
,以便他们拥有单向导航属性。此外,电话号码是可选的。我还为Contact
设置了许多关系,以防止EF在添加迁移时添加Contact_Id
列。映射如下(注意WithMany()
使用,因为PhoneNumber
没有导航属性返回Contact
):
modelBuilder.Entity<Contact>().HasMany(r => r.PhoneNumbers).WithMany()
.Map(x => x.MapLeftKey("ContactId").MapRightKey("PhoneId"));
当我添加一个包含多个电话号码的Contact
时,它会被添加正常。有Contact
,PhoneNumbers
表和ContactPhoneNumbers
链接表的记录。
然而,我正在努力解决的问题是当我删除联系人时。 EF正确删除ContactPhoneNumbers
链接表和Contact
条目中的条目,但它不会删除PhoneNumbers
表中的条目。我已经看到使用modelBuilder
进行映射的示例,其中使用了WillCascadeOnDelete(true)
,但使用WithMany()
时该选项不可用。
如何才能使这种类型的级联删除正常工作?这个设置有可能吗?或者我是否需要为每个实体(联系人和业务)设置单独的PhoneNumbers
表来设置相应的PhoneNumber表使用FK的关系(例如,Contact_Id
)?
我对EF很新,所以欢迎任何建议。我可能会完全错误。
编辑:这是相关的迁移代码......
CreateTable(
"dbo.PhoneNumbers",
c => new
{
Id = c.Int(nullable: false, identity: true),
Number = c.String()
})
.PrimaryKey(t => t.Id);
CreateTable(
"dbo.Contacts",
c => new
{
Id = c.Int(nullable: false, identity: true)
})
.PrimaryKey(t => t.Id);
CreateTable(
"dbo.ContactPhoneNumbers",
c => new
{
ContactId = c.Int(nullable: false),
PhoneId = c.Int(nullable: false),
})
.PrimaryKey(t => new { t.ContactId, t.PhoneId })
.ForeignKey("dbo.Contacts", t => t.ContactId, cascadeDelete: true)
.ForeignKey("dbo.PhoneNumbers", t => t.PhoneId, cascadeDelete: true)
.Index(t => t.ContactId)
.Index(t => t.PhoneId);
CreateTable(
"dbo.Business",
c => new
{
Id = c.Int(nullable: false),
PhoneNumberId = c.Int(nullable: false)
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.PhoneNumbers", t => t.PhoneNumberId, cascadeDelete: true)
.Index(t => t.Id)
.Index(t => t.PhoneNumberId);
答案 0 :(得分:2)
为了级联删除工作,要进行级联的记录必须将外键返回到要删除的记录。因此,在您的示例中,您删除了联系人记录。因为它们是从ContactPhoneNumber到Contact的外键,所以级联工作。由于从PhoneNumber到ContactPhoneNumber没有外键,(外键是另一种方式),级联不会继续。
这是因为您将关系定义为多对多。如果您考虑尝试按照您的意愿对模型执行级联删除,如果删除ContactPhoneNumber然后删除其关联的PhoneNumbers,现在可能有其他ContactPhoneNumbers没有有效的PhoneNumber(因为一个PhoneNumber可以有很多ContactPhoneNumbers)。现在需要删除这些,这个过程将继续。数据库不喜欢这种循环级联。
我不完全清楚为什么你需要多对多的关系,如果你真的需要它,你将无法在删除时执行级联。如果你能建立你的关系:
1联系人 - * ContactPhoneNumber 1- * PhoneNumber,然后您可以将级联配置为您想要的工作方式。