Entity framework «многие ко многим» продолжает добавлять дополнительную запись

#entity-framework #ef-code-first

#entity-framework #ef-code-first

Вопрос:

Я пытаюсь сначала добавить новую запись в таблицу ссылок, используя код entityframework. То, что у меня есть, — это многие ко многим на User и Role . Мой сценарий заключается в том, что когда я меняю роль для пользователя, я удаляю все их предыдущие роли и добавляю новые роли следующим образом:

 //Delete all associated roles for user
var roleUser = db.Users.Include(r => r.Roles).FirstOrDefault(u => u.UserId == user.UserId);
var usersRoles = roleUser.Roles;

usersRoles.ForEach(role => roleUser.Roles.Remove(role));

//add the new roles
roleUser.Roles.AddRange(detachedUser.Roles);

db.SaveChanges();
  

Таким образом, он отлично удаляет их. Но при добавлении новых ролей это добавляет их не только в таблицу ссылок, но и в Role таблицу. Добавляется совершенно новая роль без RoleName . user.Roles будет содержать элемент со следующими данными:

 RoleId;//1 <-- this Id exists in the database already but yet still it creates one instead of a linktable record.
RoleName;//null
  

Как мне запретить EF добавлять совершенно новую запись и просто добавить запись в таблицу ссылок?

Обновление: в итоге я сделал это:

 var roleUser = db.Users.Include(r => r.Roles).FirstOrDefault(u => u.UserId == user.UserId);
var roles = db.Roles;

foreach (var role in roles)
{
     if (user.Roles.Any(r => r.RoleId == role.RoleId))
     {
          roleUser.Roles.Add(role);
     }
     else
     {
         roleUser.Roles.Remove(role);
     }
}
db.SaveChanges();
  

Комментарии:

1. По-видимому, это решено, но не могу понять, что ее решило. Не могли бы вы, пожалуйста, опубликовать еще раз ту часть ответа, которая предотвращает создание новой роли.

Ответ №1:

попробуйте сохранить перед добавлением новых ролей пользователю

 //Delete all associated roles for user 
var roleUser = db.Users.Include(r => r.Roles).FirstOrDefault(u => u.UserId == user.UserId); 
var usersRoles = roleUser.Roles; 

usersRoles.ForEach(role => roleUser.Roles.Remove(role));  
db.SaveChanges(); 

roleUser.Roles.AddRange(user.Roles); //add the new roles 
db.SaveChanges(); 
  

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

Взгляните на это :

 roleUser.Roles.AddRange(user.Roles); //add the new roles 
  

откуда user.Roles берутся?

Комментарии:

1. Я все еще сталкиваюсь с той же проблемой после добавления вторых сохранений.

2. Я думаю, что это способ, которым я добавляю новые роли. Вероятно, мне придется получить их все из базы данных и добавить их

3. когда у вас возникают подобные проблемы, вы также можете захотеть взглянуть на свою конфигурацию привязки. У меня были подобные проблемы в прошлом.

4. изменило ли что-нибудь их возвращение из базы данных?

5. @lol coder, вы нашли причину создания ролей. объекты были замечены как новые. рад видеть, что вы решили эту проблему 🙂

Ответ №2:

Я думаю, проблема в том, что вам нужно прикрепить свои роли, прежде чем добавлять их пользователю.

вам также не нужно удалять их все, просто удалите удаленные, а затем только добавьте новые.

Комментарии:

1. Я согласен с @moi_meme в той части, где вам нужно удалить только те, которые необходимо удалить. С другой стороны, я не думаю, что это проблема, которая коснулась подключенных / отсоединенных состояний. поскольку объекты никогда не отсоединяются.

2. @Alexandre Brisebois — Я написал, что из-за его переменной называется DetachedUser

3. мой плохой, я не заметил эту часть

Ответ №3:

Для каждого добавляемого вами рулона вы могли бы попробовать проверить или установить состояние объекта. Например, здесь я установил для set значение unchaged. Таким образом, он не будет пытаться вставить или обновить его.

 myContext.Entry(roll).State = EntityState.Unchanged
  

Больше информации здесь:
http://blogs.msdn.com/b/adonet/archive/2011/01/29/using-dbcontext-in-ef-feature-ctp5-part-4-add-attach-and-entity-states.aspx

Комментарии:

1. верно, но если бы он сохранил перед попыткой добавления новых ролей, разве состояние объектов не осталось бы неизменным (после сохранения)