EF Core 5.0 中的多对多关系是否可以配置为仅保留一个导航属性在一侧?

问题描述

我已经使用以下代码配置了我的 DbContext(EF Core 5.0):

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<User>()
        .HasMany(p => p.Roles)
        .WithMany(p => p.Users)
        .UsingEntity<Dictionary<string,object>>("UsersToRoles",x => x.HasOne<Role>().WithMany().HasForeignKey("UserId"),x => x.HasOne<User>().WithMany().HasForeignKey("UserId"),x => x.ToTable("UsersToRoles"));

    modelBuilder.Entity<Role>()
        .ToTable("Roles")
        .Property(r => r.Application)
        .Isrequired();

    base.OnModelCreating(modelBuilder);
}

问题是我不希望 Role 实体持有 Users 的集合。我保留它是因为 EF Core 需要它来配置多对多关系。

有没有一种方法可以创建相同的关系,而无需定义 Role.Users 导航属性

解决方法

简短的回答是 - 您要问的是需要的,但尚不支持,如当前 Many-to-many 部分开头的明确说明(虽然强调不够,但没有人喜欢强调限制) EF Core 官方文档(重点是我的):

多对多关系双方都需要一个集合导航属性

在原始跟踪项Many-to-many (skip) navigation properties #19003的末尾也可以看到基本相同的问题

您好,有没有办法避免为实体之一定义属性? 例如

builder.HasMany(p => p.Tags).WithMany(); // notice no parameter in `WithMany`

团队的回应是

还没有#3864

直接指向 Support unidirectional many-to-many relationships through shadow navigations #3864,这是相应的当前未解决的问题,似乎计划发布 6.0。

至于为什么,只有团队成员可以回答这个问题,但很可能是因为通常没有足够的时间在有限的时间内完成特定版本的交付。用于实现实际功能的全新(且不完整)概念(跳过导航),具有许多可能的改进,例如 Support non-many-to-many skip navigations #21673、有问题的改进和许多其他改进 - 您可以在此处查看当前列表{ {3}}。加上技术困难,缺乏阴影导航属性支持(尽管这并不能阻止其他类型的关系,即使在任何一方都没有导航(这将如何有用是另一回事))等。>

最后一点,以防您正在寻找解决方法/克服当前限制的方法。我通常喜欢超越 EF Core 的限制,但在这里首先我没有看到值(我个人认为导航属性更像是表示 LINQ 查询中的关系而不是存储的元数据),并且还试图克服它直接使用内部元数据 API,加上难看的代码导致了不同的运行时异常,这对我来说证明当前代码确实依赖于“反向”导航,并且在很多地方都受到限制。

因此,您至少需要一个私有的 ICollection<User> Users 属性或字段,从序列化中排除并进行流畅配置

modelBuilder.Entity<User>().HasMany(e => e.Roles).WithMany("Users");

并接受这样一个事实:它将从 EF Core 导航修正填充。或者更好,只需使用公共导航属性并等待该功能的正式实施。