如何使用 Entity Framework Code First 确定多对多联结表名称?

And*_*ken 4 .net code-first entity-framework-4.1

我知道 Code-First 使用模型绑定约定,并且这是默认可用(并且处于活动状态?)的约定列表。

看来多对多关系的联结表名称的选择有点随机

使用哪个引用约定来确定连接表名称?用于确定该名称的算法是什么?

Sla*_*uma 5

我认为,多对多连接表名的一般规则是

左实体的类名 + 右实体的复数类名

因此,如果第一个实体是User,第二个实体是,则Role连接表名称是UserRoles

这可能会受到删除的影响,PluralizingTableNameConvention但我不确定。

更大的问题是确定什么是“左”实体和什么是“右”实体。我认为这几乎取决于随机因素,例如 EF 构建模型的顺序,而该顺序又取决于实体之间的导航属性以及您DbSet在派生上下文中编写 s 的顺序。因此,强烈建议使用 Fluent API 显式定义连接表名称。模型中的一个小更改或更改上下文中集合的顺序可以让 EF 认为名称必须是RoleUsers而不是前者UserRoles

这里引用了一个类似的答案

编辑

始终使用 Fluent API 显式定义多对多映射的另一个原因(与表名问题没有多大关系,但更多地与左侧实体应该是什么、右侧实体是什么的问题相关)是性能。

连接表有一个复合主键和该键上的聚集索引(至少在 SQL Server 中)。现在假设表名称为RoleUsers,左侧实体为Role,右侧实体为 ,User因为也许某些开发人员决定在上下文中按字母顺序对集合进行排序:

public DbSet<Role> Roles { get; set; }
public DbSet<User> Users { get; set; }
Run Code Online (Sandbox Code Playgroud)

连接表条目如下所示:

RoleId    UserId
----------------
1         1
1         2
2         1
2         2
3         1
3         2
Run Code Online (Sandbox Code Playgroud)

现在,应用程序中的大多数查询可能都对获取给定用户的角色感兴趣。但您并不经常或从来没有兴趣让所有用户都担任给定的角色。可以通过以下方式查询给定用户的角色Include

var user = context.Users.Include(u => u.Roles).Single(u => u.UserId == 1);
Run Code Online (Sandbox Code Playgroud)

UserId这将在连接表中的SQL 中创建一个 JOIN : ON Users.UserId = RoleUsers.UserId。此联接不能使用联接表中的索引,而是会导致表扫描以检索表中用户 RoleId 的第 1、3 和 5 行。

对于此类查询的性能更好的方法是将 用作User左实体,将Role用作右实体,从而生成对(UserId、RoleId)的聚集索引,这对于此类查询的性能更好。(当然,您可以在上面的示例中创建第二个索引以提高性能。)要实现此目的,您必须使用 Fluent API 指定映射。

因此,明智地选择左右实体而不是将这个决定留给 EF 是有意义的。