EF Core 5.0 中的多对多关系是否可以配置为仅保留一个导航属性(在一侧)? [英] Can many-to-many relationships in EF Core 5.0 be configured keeping just one navigation property (on one side)?

查看:11
本文介绍了EF Core 5.0 中的多对多关系是否可以配置为仅保留一个导航属性(在一侧)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

protected override void OnModelCreating(ModelBuilder modelBuilder){modelBuilder.Entity<用户>().HasMany(p => p.Roles).WithMany(p => p.Users).UsingEntity(UsersToRoles",x =>x.HasOne().WithMany().HasForeignKey(UserId"),x =>x.HasOne().WithMany().HasForeignKey(UserId"),x =>x.ToTable(UsersToRoles"));modelBuilder.Entity().ToTable(角色").Property(r => r.Application).是必须的();base.OnModelCreating(modelBuilder);}

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

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

解决方案

简短的回答是 - 你要问的是需要的,但还没有支持,正如明确指出的(虽然强调不够,但没有人喜欢强调局限性) 在当前 Many-to-many 官方 EF Core 文档部分(重点是我的):

<块引用>

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

也在原始跟踪项的末尾多对多(跳过)导航属性#19003你可以看到基本相同的问题

<块引用>

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

builder.HasMany(p => p.Tags).WithMany();//注意 `WithMany` 中没有参数

团队的回应是

<块引用>

还没有#3864

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

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

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

所以至少你需要一个私有的 ICollection;用户属性或字段,从序列化中排除并流畅配置

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

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

I've configured my DbContext (EF Core 5.0) with the following code:

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);
}

The thing is that I wouldn't like the Role entity to hold a collection of Users. I'm keeping it because EF Core requires it to configure the many-to-many relationship.

Is there a way to create the same relationship, but without having to define the Role.Users navigation property?

解决方案

The short answer is - what are you asking is desired, but not supported yet, as clearly stated (although not enough emphasized, but nobody likes to highlight the limitations) in the beginning of the current Many-to-many section of the official EF Core documentation (emphasis is mine):

Many to many relationships require a collection navigation property on both sides.

Also at the end of the original tracking item Many-to-many (skip) navigation properties #19003 you can see basically the same question

Hello, is there a way to avoid defining the property for one of the entities? e.g.

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

and the response from the team is

Not yet #3864

pointing straight to Support unidirectional many-to-many relationships through shadow navigations #3864, which is the corresponding current open issue, and seems like is scheduled for 6.0 release.

As of why exactly, only the team members can answer that, but most likely it's because of the usual lack of enough time to fit something in the limited timeframe for delivering a specific release. A brand new (and not fully complete) concept (skip navigations) used to implement the actual feature, with a lot of possible improvements like Support non-many-to-many skip navigations #21673, the one in question and many others - you can see the current list here Improve many-to-many, skip navigations, and indexer properties #22960. Plus technical difficulties, the lack of shadow navigation property support (although that doesn't stop the other types of relationships which can be configured even w/o a navigation at neither side (how that would be useful is another story)) etc.

A final note in case you are looking for workaround/a way to overcome the current limitation. I usually like to go beyond the EF Core limitations, but here first I don't see a value (I personally look at navigation properties more like metadata representing a relationship in the LINQ queries rather than a storage), and also attempts to overcome it with using directly internal metadata APIs, along with the ugly looking code just led to a different runtime exceptions, which to me proves that the current code really relies on having the "inverse" navigation, and that is constrained in many places.

So at minimum you need a private ICollection<User> Users property or field, excluded from serialization and fluently configured

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

and live with the fact that it will be populated from the EF Core navigation fixup. Or better off, just live with the public navigation property and wait for the official implementation of the feature.

这篇关于EF Core 5.0 中的多对多关系是否可以配置为仅保留一个导航属性(在一侧)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆