我知道Code-First使用模型绑定约定,默认情况下这是list of conventions可用(并且是活动的?)。
似乎为多对多关系选择联结表名称有点随机..
使用哪些引用的约定来确定联结表名称?用于确定该名称的算法是什么?
答案 0 :(得分:3)
我认为,多对多联接表名称的一般规则是
ClassNameOfLeftEntity + PluralizedClassNameOfRightEntity
因此,如果第一个实体是User
而第二个实体是Role
,则联接表名称为UserRoles
。
删除PluralizingTableNameConvention
可能会影响到这一点,但我不确定。
更大的问题是确定什么是“左”和什么是“正确”实体。我认为这取决于几乎随机因素,例如EF构建模型的顺序,其中依赖于实体之间的导航属性以及在派生上下文中编写DbSet
的顺序。因此,强烈建议使用Fluent API明确定义连接表名称。如果模型中的细微更改或更改上下文中集的顺序,则EF可以认为名称必须为RoleUsers
而不是前UserRoles
。
这是reference to a similar answer。
修改强>
使用Fluent API定义多对多映射的另一个原因(与表名问题没有多大关系,但更多的是左边的问题和正确的实体)是性能。
连接表在该键上有一个复合主键和一个聚簇索引(至少在SQL Server中)。现在假设表名为RoleUsers
,左实体为Role
,右实体为User
,因为可能某些开发人员决定在上下文中按字母顺序对这些集进行排序:
public DbSet<Role> Roles { get; set; }
public DbSet<User> Users { get; set; }
连接表条目如下所示:
RoleId UserId
----------------
1 1
1 2
2 1
2 2
3 1
3 2
现在,您的应用程序中的大多数查询可能都对获取给定用户的角色感兴趣。但是,对于给定角色的所有用户,您并不经常或从不感兴趣。可以通过Include
:
var user = context.Users.Include(u => u.Roles).Single(u => u.UserId == 1);
这将在连接表UserId
中的SQL中创建JOIN:ON Users.UserId = RoleUsers.UserId
。此连接不能使用连接表中的索引,而是导致表扫描以检索表中用于用户RoleIds的第1,3和5行。
这样的查询的性能更好是将User
作为左实体而Role
作为正确的实体,从而产生对的聚簇索引(UserId,RoleId),这是更好地执行此类查询。 (您当然可以在上面的示例中创建第二个索引以提高性能。)为此,您必须使用Fluent API指定映射。
因此,明智地选择左右实体并且不将此决定留给EF是有意义的。