当前位置: 动力学知识库 > 问答 > 编程问答 >

c# - Save many-to-many in EntityFramework

问题描述:

I want to show a Teacher and all assigned courses for the teacher in a listbox on edit (Many-to-Many relationship: Course, Teacher, and CourseTeacher). (I want to highlight courses that are already selected, and if user changes selection it will be reflected in the database).

My problem is that it works for Get method, but when I post to update teacher and relevant courses it doesn't do it automatically(updates teacher info, but not selected courses), though it has all of the courses assigned in object.

I'm new to MVC, so I'm not even sure if my models are correct. But I guess the problem is in the post method.(Last piece of code, please see my comments).

To be clear. I already have list of courses avaialble. I just want to associate them with several teachers.

What I've done so far: ViewModel

public class TeacherEditor

{

public Teacher Teacher { get; set; }

public int[] SelectedCourseIds { get; set; }

public MultiSelectList Courses { get; set; }

}

teacher model:

 public class Teacher

{

public int TeacherID { get; set; }

public string FirstName { get; set; }

public string LastName { get; set; }

public ICollection<Course> Courses { get; set; }

public Teacher()

{

Courses = new HashSet<Course>();

}

}

View:

 <div class="editor-field">

@Html.ListBoxFor(model=>model.SelectedCourseIds, Model.Courses)

</div>

Controller GET:

 public ActionResult Edit(int id = 0)

{

var teacher = db.Teachers.Include(x=>x.Courses).Where(x=>x.TeacherID==id).SingleOrDefault();

if (teacher==null)

{

return HttpNotFound();

}

var selectedCourses = teacher.Courses.Select(x=>x.CourseID);

var model = new TeacherEditor

{

Teacher = teacher,

Courses = new MultiSelectList(db.Courses, "CourseID", "Name", selectedCourses),

SelectedCourseIds = selectedCourses.ToArray()

};

if (model == null)

{

return HttpNotFound();

}

return View(model);

}

Controller POST:

 [HttpPost]

public ActionResult Edit(TeacherEditor teacherEditor)

{

if (ModelState.IsValid)

{

foreach (var id in teacherEditor.SelectedCourseIds)

{

Course course = db.Courses.Where(x=>x.CourseID==id).SingleOrDefault();

teacherEditor.Teacher.Courses.Add(course); //Here I'm adding courses back to Teacher object for save.

}

db.Entry(teacherEditor.Teacher).State = EntityState.Modified; /?This doesn't save records to my relationship table. Why?

db.SaveChanges();

return RedirectToAction("Index");

}

return View(teacherEditor);

}

网友答案:

Your problem is that you can't bind on a POST to an interface in MVC (ICollection). The DefaultModelBinder offers no support for binding to abstract base classes and interfaces. Change ICollection<Course> Courses to a concrete implementation like List<Course> Courses.

Then you can represent Courses with index notation in your view, ListBoxFor should handle that.

Try something like:

public class Teacher
    {
        public int TeacherID { get; set; }

        public string FirstName { get; set; }
        public string LastName { get; set; }

        public IQueryable<Course> Courses { get; set; }

        public Teacher()
        {
            Courses = new IQueryable<Course>();
        }
    } 

public class TeacherEditor
    {
        public Teacher Teacher { get; set; }
        public int[] SelectedCourseIds { get; set; }
        public List<Course> CourseList 
        {
            get { return Teacher.Courses.ToList(); }
            set { Teacher.Courses = value.ToList(); }
        }
    }
分享给朋友:
您可能感兴趣的文章:
随机阅读: