Можно ли напрямую ссылаться на таблицу "многие-ко-многим", используя структуру сущности, сначала код
Я использую структуру сущности и моделирующую отношение "многие ко многим".
Я создал связь между двумя объектами, используя свободный API (скажем, пользователи и группы):
this.HasMany(t => t.Users)
.WithMany(t => t.Groups)
.Map(
m =>
{
m.ToTable("GroupMembers");
m.MapLeftKey("Group_Id");
m.MapRightKey("User_Id");
});
Это отлично работает, но я также хочу иметь возможность напрямую ссылаться на таблицу GroupMembers. Для этого у меня есть что-то вроде:
[Table("GroupMembers")]
public class GroupMember
{
#region Properties
/// <summary>
/// Gets or sets the group.
/// </summary>
public virtual Group Group { get; set; }
/// <summary>
/// Gets or sets the Id of rht group.
/// </summary>
[Key]
[Column("Group_Id", Order = 1)]
public int GroupId { get; set; }
/// <summary>
/// Gets or sets the user.
/// </summary>
public virtual User User { get; set; }
/// <summary>
/// Gets or sets the Id of the user.
/// </summary>
[Key]
[Column("User_Id", Order = 2)]
public int UserId { get; set; }
#endregion
}
Однако при инициализации DbContext я получаю следующую ошибку:
Указанная схема недействительна. Ошибки: (381,6): ошибка 0019: EntitySet 'GroupUser' со схемой 'dbo' и table 'GroupMembers' был уже определен. Каждый EntitySet должен ссылаться на уникальную схему и таблица.
Я считаю, что это связано с тем, что инфраструктура сущности не понимает, что таблица GroupMembers, указанная в беглой API и таблице сущностей GroupMembers, фактически одна и та же. Другими словами, если я удалю свободный API-код, описывающий отношения "многие-ко-многим", я успешно смогу инициализировать DbContext.
Могу ли я иметь таблицу "многие ко многим", к которой я также могу обратиться напрямую?
Ответы
Ответ 1
Нет, вы не можете. Если вы хотите иметь доступ к таблице соединений через отдельный объект, вы должны заменить отношения "многие-ко-многим" двумя отношениями "один-ко-многим" и изменить свойства навигации в User
и Group
для ссылки на GroupMember
:
public class Group
{
public int GroupId { get; set; }
public virtual ICollection<GroupMember> Members { get; set; }
}
public class User
{
public int UserId { get; set; }
public virtual ICollection<GroupMember> Members { get; set; }
}
modelBuilder.Entity<Group>()
.HasMany(g => g.Members)
.WithRequired(gm => gm.Group);
modelBuilder.Entity<User>()
.HasMany(u => u.Members)
.WithRequired(gm => gm.User);
Зачем вам этот объект GroupMember
? Он не содержит никакого коммерческого значения и имеет только ссылки и ключи. Обычно вы можете получать и изменять любой контент таблицы соединений, записывая запросы LINQ и используя Group
и User
DbSets/entities и их навигационные свойства.
Ответ 2
Да, вы можете... Если вы используете другой Контекст. Если вы попытаетесь сопоставить несколько объектов с одной и той же таблицей в одном Контексте, вы получите ошибку. Но если вы поместите два сопоставления в отдельные Контексты, то проблем не будет. Таким образом, вы можете иметь одно сопоставление, которое описывает отношения многих-многих с прозрачной таблицей соединения, как если бы в нем были только внешние ключи... И вы можете иметь другое сопоставление со своим контекстом, чтобы показать фактическую таблицу соединений, если вы хотите получить какие-либо свойства отношений.
Ответ 3
Да, вы можете! Отметьте этот. Кроме того, удалите элемент GroupMembers и коллекцию IDbSet.
Ответ 4
Мы обошли это, создав представление, которое используется только для определения отношений. У нас были другие поля в таблице поиска, которые нам нужны для доступа.
Вид просто выбирает поля соединения из таблицы поиска.