1

我对我的 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; }
    }

这里有什么问题?我看不出有什么问题。

4

1 回答 1

2

两个实体都需要问题UserProfile

您在和 之间具有三个必需的一对多关系UserProfileSupportTicketSupportTicketMessage

  1. UserProfileSupportTicket_
  2. UserProfileSupportTicketMessage_
  3. SupportTicketSupportTicketMessage_

(左侧是主体(具有关系的主键),右侧是从属(具有关系的外键)。)

对于所需的一对多关系,EF 默认向数据库添加级联删除,即如果删除了上面左侧的实体,则应自动删除右侧的所有依赖实体。

如果您UserProfile现在要删除 a,您将有两个到表的级联删除路径SupportTicketMessage,即:

  • UserProfile-> SupportTicket-> SupportTicketMessage(因为关系 1 和 3)
  • UserProfile-> SupportTicketMessage(因为关系 2)

这在 SQL Server 中是不允许的以及异常的原因。

为了解决该问题,您必须“破坏”至少一个关系的级联删除路径。您可以通过使关系可选(即:删除[Required]导航属性上的属性之一)或显式禁用级联删除来做到这一点。我会选择后一个选项,因为将关系从必需更改为可选是一种更改业务规则。我会为关系 1 和 2 禁用级联删除,因为也许删除 aUserProfile不应该删除所有SupportTickets 和SupportTicketMessages 而是应该将票证和消息分配给一些“匿名”默认用户,因此票证历史不会丢失当用户想要离开系统时。

必须使用 Fluent API 禁用级联删除:

modelBuilder.Entity<SupportTicket>()
    .HasRequired(s => s.Owner)
    .WithMany()
    .WillCascadeOnDelete(false);

modelBuilder.Entity<SupportTicketMessage>()
    .HasRequired(s => s.Author)
    .WithMany()
    .WillCascadeOnDelete(false);

(如果您在引用 s 和 s 时有导航集合,UserProfileSupportTicket必须SupportTicketMessage使用WithMany带有 lambda 参数的调用,例如WithMany(u => u.SupportTickets)WithMany(u => u.SupportTicketMessages)。)

于 2013-08-10T13:15:19.737 回答