【问题标题】:Introducing FOREIGN KEY may cause cycles or multiple cascade paths引入 FOREIGN KEY 可能会导致循环或多个级联路径
【发布时间】:2016-07-22 03:20:09
【问题描述】:

我正在使用带有代码优先方法的实体框架。

在我的onModelCreating 中,我正在使用键和关系创建表(我使用的是 Fluent API 方法,而不是数据注释)。

但是当我尝试使用Update-Database 命令生成我的模型时,我收到以下错误

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

我几乎可以肯定我没有循环......如果我有级联路径,我不会有问题。这是我想要的!

按照我正在创建的模型:

modelBuilder.Entity<Customer>()
    .ToTable("customers", schemaName)
    .HasKey(c => new { c.Code });

modelBuilder.Entity<BillingCenter>()
    .ToTable("billingCenters", schemaName)
    .HasKey(bc => new { bc.Id });

//1 Customer -> N BillingCenters
modelBuilder.Entity<BillingCenter>()
    .HasRequired(bc => bc.Customer)
    .WithMany(c => c.BillingCenters)
    .HasForeignKey(bc => bc.CustomerId);

modelBuilder.Entity<Invoice>()
    .ToTable("invoices", schemaName)
    .HasKey(i => new { i.Id });

//Here the code gives me problems
//1 BillingCenter -> N Invoices
modelBuilder.Entity<Invoice>()
    .HasRequired(i => i.BillingCenter)
    .WithMany(bc => bc.Invoices)
    .HasForeignKey(i => i.BillingCenterId);

modelBuilder.Entity<Payment>()
    .ToTable("payments", schemaName)
    .HasKey(ep => new { ep.Id })
    .Property(ep => ep.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

//1 Customer -> N Payments
modelBuilder.Entity<Payment>()
    .HasRequired(ep => ep.customer)
    .WithMany(c => c.Payments)
    .HasForeignKey(ep => ep.customerCode);

//1 Invoice -> N Payments (Failed, Ok, ...)
modelBuilder.Entity<Payment>()
    .HasRequired(p => p.Invoice)
    .WithMany(i => i.Payments)
    .HasForeignKey(p => p.InvoiceId);

如果我删除此代码,一切似乎都正常

modelBuilder.Entity<Invoice>()
    .HasRequired(i => i.BillingCenter)
    .WithMany(bc => bc.Invoices)
    .HasForeignKey(i => i.BillingCenterId);

并生成以下数据库:

我说它似乎可以工作,因为如果我看到 billingCentersinvoices 之间的关系,delete rule 就是 no action

我该如何解决这个问题?

提前谢谢你

【问题讨论】:

    标签: entity-framework foreign-keys foreign-key-relationship cascade


    【解决方案1】:

    我几乎可以肯定我没有周期

    您确实有一个从customerspayments 的循环。如果你删除了customer,那么payment可以通过customers-&gt;paymentscustomers-&gt;billingCenters-&gt;invoices-&gt;payments删除,循环往复。

    如果我有级联路径,我不会有问题。这是我想要的!

    我确定这正是我们想要的。事实上,一些数据库(当然是 Oracle)在使用多个级联路径时没有问题。不幸的是 SqlServer 不支持它们,所以 EF 设计者决定不支持这种配置。

    我说它似乎可以工作,因为如果我看到 billingCenters 和发票之间的关系,则删除规则不会执行任何操作。

    这是因为您的迁移失败并已回滚。它确实试图设置删除级联。

    我该如何解决这个问题?

    你应该打破这个循环。您可以通过关闭级联删除(通过在各自的关系配置中包含 WillCascadeOnDelete(false))来实现此目的,至少为关系 customers-&gt;paymentscustomers-&gt;billingCenters 之一。

    这样做将“解决”问题。我的意思是您将能够成功运行迁移。但请注意,您可能会遇到维护问题 - 根据数据库处理 FK 约束的方式,可能无法简单地删除 customer 并需要在删除之前手动删除相关记录(paymentsbillingCenters)。

    【讨论】:

    • 我明白...但更准确地说...问题出在付款表上(不是发票)。如果我删除了一个客户,那么可以通过customers -&gt; billing centers -&gt; invoices -&gt; paymentscustomers -&gt; payments 删除付款...我打破了关闭级联删除的循环,只是为了关系customers -&gt; payments.. 这不应该给我任何维护问题,因为在这样我就不需要手动删除任何东西了...
    • @Ciccio 这就是我所说的至少一个 4 种关系。所以你选择customer -&gt; payments - 很好。但是如果有payments与之关联,你将无法删除customer,对吧?
    • 不,为什么?如果我删除一个customer,关联的payments 将通过customers -&gt; billing centers -&gt; invoices -&gt; payments 删除.. 所以我想我不会有任何问题...
    • 啊,我想我错过了invoices-&gt;payments 的方向(我的答案基于payments-&gt;invoices)。仍然取决于数据库将如何处理级联操作。如果它首先检查customers-&gt;payments,那么您将不走运。你试过了吗,我的意思是它有效吗?
    猜你喜欢
    • 2011-05-08
    • 2013-10-22
    • 2018-08-08
    • 2017-04-26
    • 2013-06-12
    相关资源
    最近更新 更多