Ошибка сопоставления Fluent API многие ко многим

#orm #entity-framework-4 #mapping #fluent-interface

#orm #entity-framework-4 #сопоставление #fluent-интерфейс

Вопрос:

У меня есть следующее сопоставление для поддержки таблицы «многие ко многим» (User_Role)

      modelBuilder.Entity<Role>()
        .HasMany<User>(u => u.users)
        .WithMany(r => r.roles)
        .Map(m => 
           m.MapLeftKey("role_id")
           m.MapRightKey("user_id")
           m.ToTable("User_Role"));
  

Это отлично работает при сопоставлении многих ролей пользователю и многих пользователей роли. Проблема, с которой я сталкиваюсь, заключается в том, что мне нужно добавить новую строку в таблицу User_Role через объект следующим образом:

 public class User_Role
{
   [Key Column(Order=1)]   
   public int role_id {get;set;)
   [Key Column(Order=1)]
   public int user_id {get;set;)
}
  

Всякий раз, когда я пытаюсь получить доступ к этому объекту следующим образом:

  dbContext.User_Role.Add(new User_Role {user_id ....
  

EF ищет несуществующую таблицу с именем User_Role1 … это добавление ‘1’ к имени таблицы.

Затем я попытался добавить:

   [Table("User_Role")] 
  

Это позаботится о добавлении «1», но теперь я получаю эту ошибку:

«Набор объектов ‘RoleUser’ со схемой ‘dbo’ и таблицей ‘User_Role’ уже определен. Каждый набор объектов должен ссылаться на уникальную схему и таблицу «

Я смог подтвердить, что следующие строки вместе вызывают проблему, но мне нужны они оба

  m.ToTable("User_Role") and public class User_Role..
  

Любые предложения были бы замечательными…Я в тупике.

Ответ №1:

Вы не можете представить таблицу соединений в отношениях «многие ко многим» классом сущности в вашей модели. Эта таблица соединений управляется EF, и вы не можете получить прямой доступ к этой таблице. Если вы хотите создать связь между существующим пользователем и существующей ролью, вы должны сделать это, используя эти две сущности:

 var user = dbContext.Users.Single(u => u.id == user_id);
var role = dbContext.Roles.Single(r => r.id == role_id);

// if you don't have lazy loading and don't instantiate the collection
// in the constructor, add this: user.roles = new List<Role>(); 

user.roles.Add(role);

dbContext.SaveChanges();
  

Это приведет к записи записи для новой связи (пары (user_id,role_id)) в таблицу соединений.

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

Если у вас есть только два ключевых свойства и вы не хотите загружать пользователя и роль из базы данных, вы можете работать с прикрепленными «заглушками»:

 var user = new User { id = user_id, roles = new List<Role>() };
var role = new Role { id = role_id };

dbContext.Users.Attach(user);
dbContext.Roles.Attach(role);

user.roles.Add(role);

dbContext.SaveChanges();