【问题标题】:Constraint may cause cycles or multiple cascade paths约束可能导致循环或多个级联路径
【发布时间】:2019-10-02 13:13:06
【问题描述】:

是这样的:

public class ApplicationUser : IdentityUser
{
    // omitted for the sake of brevity...

    public string LastName { get; set; }
    public string FirstName { get; set; }

    public string Email { get; set; }
}

public class Invoice
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [Index(IsUnique = true)]
    [Required]
    public int No { get; set; }

    [Required]
    public DateTime Created { get; set; }

    [Required]
    public string ManagerId { get; set; }
    public virtual ApplicationUser Manager { get; set; }

    public virtual ICollection<InvoicePayment> Payments { get; set; }
}

public class InvoicePayment
{
    [Key]
    public Guid Id { get; set; }

    [Required]
    public int InvoiceId { get; set; }
    public virtual Invoice Invoice { get; set; }

    [Required]
    public DateTime Created { get; set; }

    [Required]
    public decimal Total { get; set; }

    public string Comment { get; set; }

    public virtual ICollection<InvoicePaymentParticipant> Participants { get; set; }
}

public class InvoicePaymentParticipant
{
    [Key]
    public Guid Id { get; set; }

    [Required]
    public Guid InvoicePaymentId { get; set; }
    public virtual InvoicePayment InvoicePayment { get; set; }

    [Required]
    public string ManagerId { get; set; }
    public virtual ApplicationUser Manager { get; set; }

    [Required]
    public decimal Part { get; set; }
}

然后我尝试Update-Database 它大喊:

在表“InvoicePaymentParticipants”上引入 FOREIGN KEY 约束“relationship_name”可能会导致 > 循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 >FOREIGN KEY 约束。 无法创建约束或索引。查看以前的错误。

我误解了多级联路径的概念。

我不明白问题出在哪里,因为如果我们想删除经理,我们也希望他们的付款参与记录以及他们创建的任何发票都会被删除。

你将如何在给定的架构中解决这个问题?

【问题讨论】:

  • 这不是“多级联路径”的意思。 SQL 服务器不允许多个级联路径到达同一个表(尽管理论上是可能的),这在您的示例中发生,即在路径 Invoice->Manager、Invoice->Payments->Participants->Manager
  • 如何重新设计这些表以避免错误?
  • 将其中一种关系设为可选和/或禁用约束的级联删除(在模型构建器中)
  • IMO,您不能在非规范化列上定义受信任的 FK。像 ManagerId 是在多个地方定义的。它必须从一个地方删除或至少删除 IsRequire 属性。如果它正在抛出,请检查这样做之后错误与否。这一点也很好,例如如果您要删除类别,那么它的所有订单详细信息都应该被删除。
  • 您可能会发现这很有用dba.stackexchange.com/questions/193292/…

标签: sql-server entity-framework foreign-keys entity-framework-migrations


【解决方案1】:

当您在必需(或不可为空的)属性上创建外键关系时,默认启用级联删除,请参阅EF required relationship

这里的问题是您有 2 个从 InvoicePaymentParticipant 到您的 ApplicationUser 表的级联删除路径:

Path1: InvoicePaymentParticipant -> InvoicePayment -> Invoice -> ApplicationUser

Path2: InvoicePaymentParticipant -> ApplicationUser

这意味着,当您删除用户时,应删除以下记录:

路径 1 下的删除:

  1. 当用户被删除时,删除他的发票
  2. 当invoice被删除时,删除对应的invoice payment
  3. 当发票支付被删除时,删除对应的发票支付参与者

路径 2 下的删除:

  1. 当用户被删除时,删除他的发票支付参与者

这在 Sql Server 中是不允许的。请参阅this page 了解更多信息。

要解决这个问题,你可以重新考虑你的表结构,去掉InvoicePaymentParticipant到ApplicationUser的外键路径之一...

另一种方法是更改​​外键的级联删除行为,您可以删除ManagerId 属性之一上的[Required] 属性,并且由于string 是nullable 类型,EF 将设置key to null 删除。

您还可以更改 EF 默认行为和turn off cascading delete

【讨论】:

  • 这是个好建议,在我的应用程序中,我通常禁用级联删除约定并手动指定我希望允许级联方案的关系。考虑一下,如果用户 X 支付了发票,并且用户 X 被删除,你真的希望发票也被删除吗?如果您允许删除财务记录,则很难平衡您的账簿和维护财务历史记录。
猜你喜欢
  • 2018-12-19
  • 2010-10-25
  • 2015-05-22
  • 2020-07-25
  • 2012-09-21
相关资源
最近更新 更多