引入FOREIGN KEY可能会造成环路或多级联路径
Introducing FOREIGN KEY may cause cycles or multiple cascade paths
我正在使用 Entity Framework 代码优先方法。
在我的 onModelCreating
中,我使用键和关系创建表(我使用 Fluent API 方法,而不是数据注释)。
但是当我尝试使用 Update-Database
命令生成我的模型时,我收到以下错误
Introducing FOREIGN KEY constraint 'FK_customers.invoices_customers.billingCenters_billingCenterId' on table 'invoices' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints. Could not create constraint. See previous errors.
我几乎可以肯定我没有循环...如果我有级联路径我就不会有问题。这是我想要的!
按照我正在创建的模型:
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);
并生成以下数据库:
我说它似乎有效,因为如果我看到 billingCenters
和 invoices
之间的关系,delete rule
就是 no action
。
我该如何解决这个问题?
提前致谢
I almost sure I do not have cycles
你确实有一个从 customers
到 payments
的循环。如果你删除一个customer
,那么payment
可以通过customers->payments
或customers->billingCenters->invoices->payments
删除,因此循环
and I would not have problem if I had cascade path. It's what I would like to have instead!
我相信这正是我们想要的。事实上,一些数据库(肯定是 Oracle)在多级联路径方面没有问题。遗憾的是 SqlServer 不支持它们,因此 EF 设计者决定不支持此类配置。
I say that it SEEMS to work because if I see the relation between billingCenters and invoices the delete rule is no action.
这是因为您的迁移失败并被回滚。它确实尝试设置删除级联。
How Can I solve the problem?
你应该打破这个循环。您可以通过为关系 customers->payments
或 customers->billingCenters
中的至少一个关系关闭级联删除(通过在相应的关系配置中包含 WillCascadeOnDelete(false)
)来做到这一点。
这样做会 "solve" 问题。我的意思是您将能够 运行 成功迁移。但请注意,您可能会遇到维护问题 - 根据数据库处理 FK 约束的方式,可能无法简单地删除 customer
并需要手动删除相关记录(payments
或 billingCenters
) 在删除它之前。
我正在使用 Entity Framework 代码优先方法。
在我的 onModelCreating
中,我使用键和关系创建表(我使用 Fluent API 方法,而不是数据注释)。
但是当我尝试使用 Update-Database
命令生成我的模型时,我收到以下错误
Introducing FOREIGN KEY constraint 'FK_customers.invoices_customers.billingCenters_billingCenterId' on table 'invoices' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints. Could not create constraint. See previous errors.
我几乎可以肯定我没有循环...如果我有级联路径我就不会有问题。这是我想要的!
按照我正在创建的模型:
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);
并生成以下数据库:
我说它似乎有效,因为如果我看到 billingCenters
和 invoices
之间的关系,delete rule
就是 no action
。
我该如何解决这个问题?
提前致谢
I almost sure I do not have cycles
你确实有一个从 customers
到 payments
的循环。如果你删除一个customer
,那么payment
可以通过customers->payments
或customers->billingCenters->invoices->payments
删除,因此循环
and I would not have problem if I had cascade path. It's what I would like to have instead!
我相信这正是我们想要的。事实上,一些数据库(肯定是 Oracle)在多级联路径方面没有问题。遗憾的是 SqlServer 不支持它们,因此 EF 设计者决定不支持此类配置。
I say that it SEEMS to work because if I see the relation between billingCenters and invoices the delete rule is no action.
这是因为您的迁移失败并被回滚。它确实尝试设置删除级联。
How Can I solve the problem?
你应该打破这个循环。您可以通过为关系 customers->payments
或 customers->billingCenters
中的至少一个关系关闭级联删除(通过在相应的关系配置中包含 WillCascadeOnDelete(false)
)来做到这一点。
这样做会 "solve" 问题。我的意思是您将能够 运行 成功迁移。但请注意,您可能会遇到维护问题 - 根据数据库处理 FK 约束的方式,可能无法简单地删除 customer
并需要手动删除相关记录(payments
或 billingCenters
) 在删除它之前。