Reputation: 3480
I know that Code-First uses conventions for model binding, and that this is the list of conventions that are available (and active?) by default.
It seems that the selection of the junction table name for Many-to-Many relationships is a little bit random..
Which of the referenced conventions is used to determine the junction table name? What is the algorithm used to determine that name?
Upvotes: 4
Views: 1023
Reputation: 177133
I think, the general rule for the many-to-many join table name is
ClassNameOfLeftEntity + PluralizedClassNameOfRightEntity
So, if the first entity is User
and the second is Role
the join table name is UserRoles
.
It is possible that this can be influenced by removing the PluralizingTableNameConvention
but i am not sure.
The bigger problem is to determine what is the "left" and what the "right" entity. I think it depends on almost random factors, like the order which EF builds the model in which in turn depends on navigation properties between entities and the order in which you have written the DbSet
s in your derived context. For this reason it is strongly recommended to define the join table name explicitely with Fluent API. A small change in your model or changing the order of the sets in your context can EF let think the name must be RoleUsers
instead of the former UserRoles
.
Here is a reference to a similar answer.
Edit
Another reason to define the many-to-many mapping always explicitely with Fluent API (not that much related to the table name question but more to the question what should be the left and what the right entity) is performance.
The join table has a compound primary key and a clustered index on that key (at least in SQL Server). Now assume the table name would be RoleUsers
and the left entity is Role
and the right entity is User
because perhaps some developer decided to sort the sets alphabetically in the context:
public DbSet<Role> Roles { get; set; }
public DbSet<User> Users { get; set; }
The join table entries would look like this:
RoleId UserId
----------------
1 1
1 2
2 1
2 2
3 1
3 2
Now, possibly the majority of queries in your application are interested in getting the roles for a given user. But you are not often or never interested to get all users for a given role. The roles of a given user could be queried by an Include
:
var user = context.Users.Include(u => u.Roles).Single(u => u.UserId == 1);
This would create a JOIN in SQL on the UserId
in the join table: ON Users.UserId = RoleUsers.UserId
. This join cannot use the index in the join table but instead results in a table scan to retrieve row 1, 3 and 5 in the table for the user's RoleIds.
Better for performance of queries like this is to have the User
as the left entity and the Role
as the right entity, resulting in a clustered index for the pair (UserId, RoleId) which is better for performance of such queries. (You could of course create a second index in the example above to improve the performance.) To achieve this you must specify the mapping with Fluent API.
So, it makes sense to choose the left and right entity wisely and to not leave this decision to EF.
Upvotes: 5