【问题标题】:EF Code First - WithMany()EF 代码优先 - WithMany()
【发布时间】:2023-03-21 16:20:01
【问题描述】:
我最近来上课ManyNavigationPropertyConfiguration<TEntity, TTarget>
,在该类中,我发现了一个名为 WithMany() 的方法,其中包含 2 个重载。
第一个重载:
WithMany()
将关系配置为
many:many 没有导航
另一边的财产
关系。
第二个重载:
WithMany(Expression<Func<TTarget, ICollection<TEntity>>>)
将关系配置为
many:many 带有导航属性
在关系的另一端。
现在我的问题是,为什么要将关系配置为 many:many 而没有导航属性(第一个重载)?我没有看到任何有用的情况...有什么想法吗?
【问题讨论】:
标签:
c#
entity-framework
ef-code-first
【解决方案1】:
一个例子可能是这个模型:
public class User
{
public int UserId { get; set; }
public string Name { get; set; }
public ICollection<Role> Roles { get; set; }
}
public class Role
{
public int RoleId { get; set; }
public string Description { get; set; }
}
如果您对检索具有特定角色的所有用户不感兴趣,请添加导航属性...
public ICollection<User> Users { get; set; }
...到Role 类将是不必要的开销。
但您仍然必须 EF 告知 User 和 Role 之间存在多对多关系...
modelBuilder.Entity<User>()
.HasMany(u => u.Roles)
.WithMany();
...因为默认的约定映射会创建一个错误的关系,即一对多的关系,对应这个映射:
modelBuilder.Entity<User>()
.HasMany(u => u.Roles)
.WithOptional();
【解决方案2】:
请注意,导航属性的选择在目标的另一侧。
让我们看一个例子,尽管这个特定案例可能不是我观点的完美例证......如果你想跟踪数学测试并重复使用问题,你可能有两个表 (@987654321 @ 和 Questions) 具有多对多关系;每个测试有几个问题,每个问题可以出现在几个测试中。但是,您可能永远不需要获取特定问题所在的测试集合 - 即使您知道问题可以出现在多个测试中,但您对哪个测试不感兴趣。
因此,您在声明它时使用了.WithMany() 重载,因此您获得了一个导航属性来获取测试问题(theTest.Questions()),但没有导航属性(theQuestion.Tests())。但是您仍然需要多对多关系,因为测试和问题都可以有许多其他关系。
我同意在这种特定情况下,这种设置可能没有意义,但在某些情况下确实如此,在这些情况下,.WithMany() 重载让您无需定义属性(以及每个属性的 lambda 表达式)即可你永远不需要。