And*_*ken 4 .net code-first entity-framework-4.1
我知道 Code-First 使用模型绑定约定,并且这是默认可用(并且处于活动状态?)的约定列表。
看来多对多关系的联结表名称的选择有点随机。
使用哪个引用约定来确定连接表名称?用于确定该名称的算法是什么?
我认为,多对多连接表名的一般规则是
左实体的类名 + 右实体的复数类名
因此,如果第一个实体是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 是有意义的。