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

Sup*_*JMN 3 .net c# many-to-many navigation-properties entity-framework-core

我已经使用以下代码配置了我的 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);
}
Run Code Online (Sandbox Code Playgroud)

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

有没有办法创建相同的关系,但不必定义Role.Users导航属性?

Iva*_*oev 5

简短的回答是 - 您要问的是需要的,但尚未得到支持,正如官方 EF当前多对多部分开头所述(虽然强调不够,但没有人喜欢强调限制)核心文档(重点是我的):

多对多关系需要双方的集合导航属性

另外在原追踪项Many-to-many (skip) navigation properties #19003的最后可以看到基本相同的问题

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

builder.HasMany(p => p.Tags).WithMany(); // notice no parameter in `WithMany`
Run Code Online (Sandbox Code Playgroud)

团队的回应是

还没有 #3864

直接指向通过阴影导航#3864 支持单向多对多关系,这是相应的当前未解决的问题,似乎计划在 6.0 版本中发布。

至于具体原因,只有团队成员可以回答,但很可能是因为通常没有足够的时间在有限的时间范围内适应特定版本的发布。用于实现实际功能的全新(且不完整)概念(跳过导航),有很多可能的改进,例如支持非多对多跳过导航#21673,有问题的和许多其他 - 你可以在此处查看当前列表改进多对多、跳过导航和索引器属性 #22960。加上技术困难,缺乏阴影导航属性支持(尽管这并不能阻止其他类型的关系,即使在任何一方都没有导航(这将如何有用是另一回事))等。

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

所以至少你需要一个私有ICollection<User> Users属性或字段,从序列化中排除并流畅地配置

modelBuilder.Entity<User>().HasMany(e => e.Roles).WithMany("Users");
Run Code Online (Sandbox Code Playgroud)

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