gpt4 book ai didi

c# - EF Core 多对多自连接

转载 作者:太空宇宙 更新时间:2023-11-03 20:58:12 27 4
gpt4 key购买 nike

我正在尝试描述与 Entity Framework Core 2 的多对多自引用关系。本质上,我正在尝试建模的是一种树结构,其中每个元素都可以有任意数量的父元素和子元素(所以我猜更多的是图而不是树)。这是我到目前为止所拥有的:

public class OrgLevel
{
...

public ICollection<OrgLevelOrgLevels> OrgLevelOrgLevelsAsParent { get; set; }

public ICollection<OrgLevelOrgLevels> OrgLevelOrgLevelsAsChild { get; set; }

public ICollection<OrgLevel> ParentOrganizationStructureLevels { get; set; }

public ICollection<OrgLevel> ChildOrganizationStructureLevels { get; set; }
}

public class OrgLevelOrgLevels
{
public OrgLevel ParentOrgLevel { get; set; }
public OrgLevel ChildOrgLevel { get; set; }
}

public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string>
{
...

protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);

builder.Entity<OrgLevelOrgLevels>()
.HasKey(t => new { t.ParentOrgLevel, t.ChildOrgLevel });

builder.Entity<OrgLevelOrgLevels>().HasOne(olol => olol.ChildOrgLevel)
.WithMany(col => col.OrgLevelOrgLevelsAsChild);

builder.Entity<OrgLevelOrgLevels>().HasOne(olol => olol.ParentOrgLevel)
.WithMany(pol => pol.OrgLevelOrgLevelsAsParent);
}
}

当我尝试生成初始迁移时,我得到以下信息:

无法将导航属性“ChildOrgLevel”添加到实体类型“OrgLevelOrgLevels”,因为实体类型“OrgLevelOrgLevels”上已存在同名属性。

我假设这意味着对于连接表,它试图将两列命名为相同的东西,因为它们引用同一个表。

此外,我真的不知道如何在 OrgLevel 模型中连接最后两个导航属性,以便它们将使用连接表来解析。

如有任何帮助,我们将不胜感激!

最佳答案

主要问题是以下流畅的配置:

builder.Entity<OrgLevelOrgLevels>()
.HasKey(t => new { t.ParentOrgLevel, t.ChildOrgLevel });

错误信息有点误导。此重载需要 primitive 属性(显式或 shadow ),但您传递的是 navigation properties .

有几种方法可以解决。

首先,向模型添加显式 FK 属性(假设引用的 PK 属性类型为 int):

public class OrgLevelOrgLevels
{
public int ParentOrgLevelId { get; set; }
public OrgLevel ParentOrgLevel { get; set; }
public int ChildOrgLevelId { get; set; }
public OrgLevel ChildOrgLevel { get; set; }
}

和使用

builder.Entity<OrgLevelOrgLevels>()
.HasKey(t => new { t.ParentOrgLevelId, t.ChildOrgLevelId });

另一种方法是保持模型不变,但使用另一个 HasKey 重载并在定义它们之后传递影子属性名称:

builder.Entity<OrgLevelOrgLevels>().HasOne(olol => olol.ChildOrgLevel)
.WithMany(col => col.OrgLevelOrgLevelsAsChild)
.OnDelete(DeleteBehavior.Restrict);

builder.Entity<OrgLevelOrgLevels>().HasOne(olol => olol.ParentOrgLevel)
.WithMany(pol => pol.OrgLevelOrgLevelsAsParent);

builder.Entity<OrgLevelOrgLevels>()
.HasKey("ParentOrgLevelId", "ChildOrgLevelId");

当然你可以提前显式定义它们:

builder.Entity<OrgLevelOrgLevels>()
.Property<int>("ParentOrgLevelId");

builder.Entity<OrgLevelOrgLevels>()
.Property<int>("ChildOrgLevelId");

builder.Entity<OrgLevelOrgLevels>()
.HasKey("ParentOrgLevelId", "ChildOrgLevelId");

builder.Entity<OrgLevelOrgLevels>().HasOne(olol => olol.ChildOrgLevel)
.WithMany(col => col.OrgLevelOrgLevelsAsChild)
.OnDelete(DeleteBehavior.Restrict);

builder.Entity<OrgLevelOrgLevels>().HasOne(olol => olol.ParentOrgLevel)
.WithMany(pol => pol.OrgLevelOrgLevelsAsParent);

注意该模型引入了多条级联路径,因此需要至少关闭两种关系中的一种级联删除,手动处理。

关于c# - EF Core 多对多自连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48213046/

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