Как определяется имя соединительной таблицы «многие ко многим» с помощью Entity Framework Code First? - PullRequest
2 голосов
/ 14 декабря 2011

Я знаю, что Code-First использует соглашения для привязки модели, и это список соглашений , которые доступны (и активны?) По умолчанию.

Это кажется, что выбор имени соединительной таблицы для отношений "многие ко многим" немного случайный.

Какое из упомянутых соглашений используется для определения имени соединительной таблицы?Какой алгоритм используется для определения этого имени?

1 Ответ

3 голосов
/ 14 декабря 2011

Я думаю, общее правило для имени таблицы объединения «многие ко многим»:

ClassNameOfLeftEntity + PluralizedClassNameOfRightEntity

Итак, если первая сущность - User а второе - Role имя таблицы соединений - UserRoles.

Возможно, на это может повлиять удаление PluralizingTableNameConvention, но я не уверен.

большая проблема состоит в том, чтобы определить, что такое «левый» и что такое «правый» объект.Я думаю, что это зависит от почти случайных факторов, таких как порядок, в котором EF строит модель, в которой, в свою очередь, зависит от свойств навигации между сущностями и порядка, в котором вы записали DbSet в производном контексте.По этой причине настоятельно рекомендуется явно определять имя таблицы соединений с помощью Fluent API.Небольшое изменение в вашей модели или изменение порядка наборов в вашем контексте может привести к тому, что EF будет думать, что имя должно быть RoleUsers вместо прежнего UserRoles.

Вот ссылка нааналогичный ответ .

Редактировать

Еще одна причина для определения сопоставления «многие ко многим» всегда явным образом с помощью 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);

Это создаст JOIN в SQL на UserId в таблице соединений: ON Users.UserId = RoleUsers.UserId.Это соединение не может использовать индекс в таблице соединений, но вместо этого приводит к сканированию таблицы для получения строк 1, 3 и 5 в таблице для пользовательских RoleIds.

Лучше для выполнения таких запросов, как это иметьUser как левая сущность и Role как правая сущность, что приводит к кластерному индексу для пары (UserId, RoleId), который лучше подходит для выполнения таких запросов.(Конечно, вы могли бы создать второй индекс в приведенном выше примере для повышения производительности.) Для достижения этого вы должны указать отображение с помощью Fluent API.

Итак, имеет смысл выбирать левый и правый объект с умоми не оставлять это решение EF.

...