外键约束问题?
Posted
技术标签:
【中文标题】外键约束问题?【英文标题】:Foreign key constraint issue? 【发布时间】:2013-08-12 06:49:39 【问题描述】:我对我的 EF 代码优先数据库进行了一些更改,当我尝试更新它时,我现在收到以下错误:
在表“SupportTicketMessages”上引入 FOREIGN KEY 约束“FK_dbo.SupportTicketMessages_dbo.SupportTickets_Ticket_Id”可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。
这是我的实体:
支持票:
public class SupportTicket
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id get; set;
[Required]
public string Title get; set;
[Required]
public string Text get; set;
[Required]
public TicketUrgency Urgency get; set;
[Required]
public TicketStatus Status get; set;
[Required]
public virtual UserProfile Owner get; set;
[Required]
public DateTime Date get; set;
SupportTicketMessage:
public class SupportTicketMessage
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id get; set;
[Required]
public virtual UserProfile Author get; set;
[Required]
public string Text get; set;
[Required]
public DateTime Date get; set;
[Required]
public virtual SupportTicket Ticket get; set;
[Required]
public int MessageNumber get; set;
这里有什么问题?我看不出有什么问题。
【问题讨论】:
您已指定级联删除...***.com/questions/10523291/… - 类似问题 @MilenPavlov 但我不明白问题出在哪里。而且我从来没有指定级联删除 【参考方案1】:问题是两个实体都需要UserProfile
。
UserProfile
、SupportTicket
和 SupportTicketMessage
之间存在三个必需一对多关系:
-
一个
UserProfile
- 许多SupportTicket
s
一个UserProfile
- 许多SupportTicketMessage
s
一个SupportTicket
- 许多SupportTicketMessage
s
(左侧是主体(具有关系的主键),右侧是从属(具有关系的外键)。)
对于所需的一对多关系,EF 默认会向数据库添加级联删除,即如果删除了上面左侧的实体,则应自动删除右侧的所有依赖实体。
如果您现在要删除 UserProfile
,您将有两个级联删除路径到 SupportTicketMessage
表,即:
UserProfile
-> SupportTicket
-> SupportTicketMessage
(因为关系 1 和 3)
UserProfile
-> SupportTicketMessage
(因为关系 2)
这在 SQL Server 中是不允许的以及异常的原因。
为了解决问题,您必须“破坏”至少一个关系的级联删除路径。您可以通过使关系可选(即:删除导航属性上的[Required]
属性之一)或显式禁用级联删除来做到这一点。我会选择后一个选项,因为将关系从 required 更改为 optional 有点改变业务规则。我会为关系 1 和 2 禁用级联删除,因为也许删除 UserProfile
不应该删除所有 SupportTicket
s 和 SupportTicketMessage
s 而是应该将票证和消息分配给一些“匿名”默认用户,所以当用户想要离开系统时,工单历史不会丢失。
必须使用 Fluent API 禁用级联删除:
modelBuilder.Entity<SupportTicket>()
.HasRequired(s => s.Owner)
.WithMany()
.WillCascadeOnDelete(false);
modelBuilder.Entity<SupportTicketMessage>()
.HasRequired(s => s.Author)
.WithMany()
.WillCascadeOnDelete(false);
(如果您在 UserProfile
中有导航集合引用 SupportTicket
s 和 SupportTicketMessage
s,则必须使用带有 lambda 参数的 WithMany
调用,例如 WithMany(u => u.SupportTickets)
和 WithMany(u => u.SupportTicketMessages)
。)
【讨论】:
哇,多么高质量的答案!非常感谢,我现在明白了 - 效果很好!非常感谢您的帮助。以上是关于外键约束问题?的主要内容,如果未能解决你的问题,请参考以下文章