gpt4 book ai didi

c# - Entity Framework 级联删除 - FOREIGN KEY 约束

转载 作者:行者123 更新时间:2023-11-30 14:53:39 25 4
gpt4 key购买 nike

我对以下模型有疑问:

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

public Guid? HeaderId { get; set; }
public ProjectPage Header { get; set; }

public Guid? FooterId { get; set; }
public ProjectPage Footer { get; set; }
}

在创建模型时我有这个:

modelBuilder.Entity<ProjectPage>().HasOptional(p => p.Header).WithMany().HasForeignKey(p => p.HeaderId).WillCascadeOnDelete(true);
modelBuilder.Entity<ProjectPage>().HasOptional(p => p.Footer).WithMany().HasForeignKey(p => p.FooterId).WillCascadeOnDelete(true);

但是我无法更新数据库。我在程序包管理器控制台中遇到以下错误:

Introducing FOREIGN KEY constraint 'FK_dbo.ProjectPages_dbo.ProjectPages_FooterId' on table 'ProjectPages' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.

有人可以解释如何删除项目页面(可以是另一个项目页面中的页脚或页眉)吗?

最佳答案

当您有多个级联删除路径可能最终尝试删除数据库中的同一行时,会导致该异常。想象一下,如果您的 ProjectPage 具有相同的 HeaderFooter。当您尝试删除该 ProjectPage 时,由于您的关系配置,将有两条路径试图删除数据库中的同一行(一个用于 Header ,另一个页脚)。

您可以通过使用 Fluent API 在两个关系之一中禁用级联删除来避免此类不明确的删除路径。或者通过将某些关系定义为可选关系(使用可为空的外键,但您不能配置与级联删除的关系)。

更新

是的,您将两个 FK 作为可选值,但两个关系都配置了级联删除,这就是 EF 抛出该异常的原因。我的建议是只设置一个与级联删除的关系。关于其他关系,恐怕您必须手动进行。例如,如果您选择手动删除 Footer,那么当您要删除 ProjectPage 时,您必须设置 Footer属性为 null。这里的问题是您的数据库中可能有孤儿。为避免这种情况,您可以覆盖上下文中的 SaveChanges 以查找和删除孤儿:

public override int SaveChanges()
{
ProjectPages
.Local
.Where(r => r.Footer== null && r.FooterId!=default(Guid)).Select(r=>r.FooterId)
.ToList()
.ForEach(id => ProjectPages.Remove(ProjectPages.Find(id)));

return base.SaveChanges();
}

另一种方法是将 FooterId 设置为 default(Guid) 值。由于您的 PK 属性 (Id) 的类型是 Guid 而不是 Identity,您必须在添加 ProjectPage 之前设置该属性到数据库。因此,将 FooterId 设置为 default(Guid) 是标记要删除的实体的另一种方法。如果您选择此变体,您的 SaveChanges 方法可能如下所示:

 public override int SaveChanges()
{
ProjectPages
.Local
.Where(r => r.Footer!= null && r.FooterId!=default(Guid)).Select(r=>r.Footer)
.ToList()
.ForEach(pp=> ProjectPages.Remove(pp));

return base.SaveChanges();
}

或者:

 public override int SaveChanges()
{
ProjectPages
.Local
.Where(r => r.Footer!= null && r.FooterId!=default(Guid)).Select(r=>r.Footer)
.ToList()
.ForEach(pp=> Entry(pp).State=EntityState.Deleted);

return base.SaveChanges();
}

这样你就可以避免调用Find方法。

关于c# - Entity Framework 级联删除 - FOREIGN KEY 约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28748082/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com