2015-12-22 5 views
1

Я не обновляю отношения «многие ко многим». Когда я отлаживаю «Response.Write(teacher.skills);», значения выглядят правильно, но база данных не обновляет объект.ASP.net MVC Entity framework update Многие для многих отношений

[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult Edit([Bind(Include = "id,lastname,firstname,image,campusId,skillIds")] Teacher teacher) 
{ 
    if (ModelState.IsValid) 
    { 
     if (teacher.skillIds != null) 
     { 
      teacher.skills = (from t in db.Skills.ToList() where teacher.skillIds.Contains(t.id) select t).ToList(); 
     } 

     Response.Write(teacher.skills); 

     // 1st attempt --> 
     //db.Teachers.Attach(teacher); 
     //db.Entry(teacher).State = EntityState.Modified; 

     // 2nd attempt --> 
     UpdateModel(teacher); 


     db.SaveChanges(); 
     return RedirectToAction("Index"); 
    } 
    return View(teacher); 
} 
+0

Сначала необходимо получить объект (учитель) из базы данных. Затем вы обновляете нужные поля и вызываете db.Entry (учитель) .State = EntityState.Modified и SaveChanges. – jpgrassi

+0

Thx @jpgrassi, теперь я могу добавить элементы, но я не могу их удалить. Я предполагаю, что мне нужно удалить их вручную из массива навыков? – jsprds

+0

Я не получил детали. Можете ли вы обновить свой вопрос? – jpgrassi

ответ

3

Не очищайте навыки. Фактически это означает, что Entity Framework удаляет все существующие отношения из таблицы соединений, а затем снова добавляет совершенно новые отношения.

При обновлении отношений M2M вы не можете просто установить свойство. Вы должны сначала удалить все невыбранные элементы, а затем добавить новые элементы, оставив при этом существующие элементы в одиночку:

[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult Edit(int id, TeacherViewModel model) 
{ 
    var teacher = db.Teachers.Find(id); 
    if (teacher == null) 
    { 
     return new HttpNotFoundResult(); 
    } 

    if (ModelState.IsValid) 
    { 
     teacher.firstname = model.lastname; 
     teacher.lastname = model.lastname; 
     teacher.image = model.image; 
     teacher.campusId = model.campusId; 

     // Remove deselected skills 
     teacher.skills.Where(m => !model.skillIds.Contains(m.Id)) 
      .ToList().ForEach(skill => teacher.skills.Remove(skill)); 

     // Add new skills 
     var existingSkillIds = teacher.skills.Select(m => m.Id); 
     db.Skills.Where(m => model.skillIds.Exclude(existingSkillIds).Contains(m.Id)) 
      .ToList().ForEach(skill => teacher.skills.Add(skill)); 

     db.SaveChanges(); 
     return RedirectToAction("Index"); 
    } 

    return View(model); 
} 

Как вы можете видеть, я добавил модель представления, которые вы должны всегда использовать в любое время вы чувствуете необходимо добавить Bind. Просто не используйте Bind. Я также передаю идентификатор обучения как часть URL-адреса. Вы не должны публиковать идентификатор. Никогда не включайте ничего в ваше тело сообщения, которое вы не хотите изменять. Я использую этот идентификатор, чтобы выбрать нового учителя из базы данных. Вы никогда не должны напрямую сохранять объект, который был отправлен. Затем появляется новый код, который удаляет отмененные навыки и добавляет новые выбранные навыки.

Смежные вопросы