【问题标题】:Issues with many-to-many relation in EF coreEF核心中的多对多关系问题
【发布时间】:2018-11-11 20:19:49
【问题描述】:

我正在尝试在实体Project 和实体Resource 之间建立多对多关系。我创建了一个关系实体:ProjectResource。我已经使用这样的 fluent API 设置了关系:

modelBuilder.Entity<ProjectResource>()
    .HasKey(pr => new { pr.ProjectId, pr.ResourceId });

modelBuilder.Entity<ProjectResource>()
    .HasOne(pr => pr.Project)
    .WithMany(p => p.ProjectResources)
    .HasForeignKey(pr => pr.ProjectId);

modelBuilder.Entity<ProjectResource>()
    .HasOne(pr => pr.Resource)
    .WithMany(r => r.ProjectResources)
    .HasForeignKey(pr => pr.ResourceId);

以下是我的课程ProjectResources 的简要定义(我只包括那种关系):

public class Resource
{
    public Guid DepartmentId { get; set; }
    public Department Department { get; set; }

    public Guid? ManagerId { get; set; }
    public Resource Manager { get; set; }

    public ICollection<Resource> Resources { get; set; }
    public ICollection<ProjectResource> ProjectResources { get; set; }
    public ICollection<ChangeLog> ChangeLogs { get; set; }
    public ICollection<Requirement> Requirements { get; set; }
    public ICollection<UseCase> UseCases { get; set; }  
}

public class Project
{
    public Guid ResponsibleId { get; set; }
    public Resource Responsible { get; set; }

    public ICollection<ProjectResource> ProjectResources { get; set; }
    public ICollection<BusinessNeed> BusinessNeeds { get; set; }
    public ICollection<SuccessCriteria> SuccessCriterias { get; set; }
    public ICollection<Requirement> Requirements { get; set; }
    public ICollection<UseCase> UseCases { get; set; }
    public ICollection<ChangeLog> ChangeLogs { get; set; }
    public ICollection<GlossaryWord> GlossaryWords { get; set; }
}

public class ProjectResource
{
    public Guid ProjectId { get; set; }
    public Project Project { get; set; }
    public Guid ResourceId { get; set; }
    public Resource Resource { get; set; }
}

我已经研究了这个问题,但似乎找不到解决方案。我已经按照here 中描述的指南完成了。

我收到以下错误:

在表“ProjectResources”上引入 FOREIGN KEY 约束“FK_ProjectResources_Resources_ResourceId”可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。

我到底做错了什么?

【问题讨论】:

  • ProjectResource 是否有一个通用实体的 FK(例如 User 或其他东西)?
  • @IvanStoev 不,他们没有,但我不确定这与我的问题有什么关系?
  • 因为它会创建您的循环或多个级联路径问题。想象一下这个结构:A -> B -> BC 和 A -> C -> BC 其中 -> 是与级联删除的一对多关系。在您的情况下,B 是 Project,C 是 Resource,BC 是 ProjectResource,我要的是 A。因为 B、C、BC 无法创建循环/多级联路径。必须有其他未在此处显示的内容导致问题。仅使用帖子中的代码创建一个干净的新项目,您会发现它没有发生。
  • @IvanStoev 好的,我明白你的意思了。我已经更新了 SO。如果您在上述课程中发现问题,您能否进一步解释一下?
  • 是的,我看到了。因此,您在 B 和 C 之间有第二种关系,而不是 A,这是另一种创建循环的方式。见下文。

标签: asp.net-core entity-framework-core


【解决方案1】:

问题是由ResourceProject之间现有的required(因此cascade delete)一对多关系引起的,由Responsible中的Responsible/ResponsibleId属性表示。

这是从ResourceProjectResource 的多个级联路径:

Resource (Id) -> (ResponsibleId) Project (Id) -> (ProjectId) ProjectResource
Resource (Id) -> (ResourceId) ProjectResource

解决多个级联路径的唯一方法是通过关闭至少一个关系的级联删除来打破循环,并手动或通过数据库触发器处理删除。

对于这个具体模型,可能最简单的方法是关闭 Resource -> Project 关系的删除级联:

modelBuilder.Entity<Project>()
    .HasOne(p => p.Responsible)
    .WithMany()
    .OnDelete(DeleteBehavior.Restrict);

【讨论】:

  • 这似乎确实解决了这个问题,但前提是我在ProjectResource 和两个关系表之间的关系上将删除行为设置为RestrictmodelBuilder.Entity&lt;ProjectResource&gt;().Hasone(pr =&gt; pr.Project).WithMany().HasForeignKey(pr =&gt; pr.ProjectId).OnDelete(DeleteBehavior.Restrict)
  • 确实,它必须设置在破坏所有循环的最小位置。我只查看这 3 个实体(注释掉了其他关系),并在我在答案中提到的地方打破了对我有用的地方。顺便说一句,所有多级联路径问题都是 SqlServer 特定的。并且可能也适用于其他一些数据库类型。但是像 Oracle 这样的一些数据库可以毫无问题地处理它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-20
  • 1970-01-01
  • 2020-05-15
  • 1970-01-01
  • 2017-02-08
  • 2018-05-27
相关资源
最近更新 更多