Entity Framework отношения «многие ко многим» добавляет конечные элементы ДО добавления отношения - PullRequest
2 голосов
/ 18 ноября 2011

Я создал очень простой объектный фреймворк для базы данных, первый проект, использующий общий сценарий «Студенты и курсы».

  • Студент может иметь много курсов
  • Курс может иметь много студентов

Я установил отношения в базе данных, и EF создал для этого хороший элемент навигации «многие ко многим».

Проблема , когда я добавляю курс студенту, курс пере-добавляется в таблицу курса, затем отношения добавляются в базу данных, что приводит к увеличению числа дублируемых курсов

это сводит меня с ума, есть идеи, что я могу делать неправильно?

Часть моего кода ....

Я создал класс Partial поверх сгенерированного объекта выше, так что у меня может быть EditorTemplate с флажком, который позволит пользователю отметить курс, чтобы добавить

public partial class Course
{
    public bool isSelected { get; set; }
}

public partial class Course
{
    public Course()
    {
        this.Students = new HashSet<Student>();
    }

    public int CourseId { get; set; }
    public string CourseName { get; set; }

    public virtual ICollection<Student> Students { get; set; }
}

Шаблон редактора для курсов

@model University.Models.Course

<div>
    @Html.CheckBoxFor(m => m.isSelected)
    @Html.DisplayFor(m => m.CourseName)


    @Html.HiddenFor(m => m.CourseName)
    @Html.HiddenFor(m =>m.CourseId)
</div>

Создать представление для студента

@model University.Models.CreateStudentViewModel            
@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Student</legend>            
        <div class="editor-label">
            @Html.LabelFor(model => model.student.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.student.Name)
            @Html.ValidationMessageFor(model => model.student.Name)
        </div>    
        <div>        
            @Html.EditorFor(m=>m.courses)
        </div>
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

ViewModel для страницы

public class CreateStudentViewModel
{
    public Student student { get; set; }
    public ICollection<Course> courses { get; set; }
}

Контроллер

public ActionResult Create()
{
    CreateStudentViewModel vm = new CreateStudentViewModel();
    vm.courses = db.Courses.ToList();
    return View(vm);
} 
[HttpPost]
public ActionResult Create(CreateStudentViewModel model)
{
    if (ModelState.IsValid)
    {
        model.student.Courses = model.courses.Where(m => m.isSelected == true).ToList();
        db.Students.Add(model.student);
        db.SaveChanges();
        return RedirectToAction("Index");  
    }
    return View(model);
}

Любая помощь, указывающая мне правильное направление, будет С благодарностью

1 Ответ

3 голосов
/ 19 ноября 2011

Вы должны прикрепить выбранные курсы к контексту в вашем посте до того, как вы добавите студента в контекст. В противном случае EF предполагает, что весь граф объектов - студент, включая все курсы - новый и должен быть вставлен в базу данных. Прилагая (= перевод курсов в состояние Unchanged), вы сообщаете EF, что не хотите, чтобы присоединенные курсы вставлялись в виде новых строк, а только создавали связь между новым студентом и существующими курсами:

[HttpPost]
public ActionResult Create(CreateStudentViewModel model)
{
    if (ModelState.IsValid)
    {
        model.student.Courses =
            model.courses.Where(m => m.isSelected == true).ToList();

        foreach (var course in model.student.Courses)
            db.Courses.Attach(course);
        // now each course is in state Unchanged in the context

        db.Students.Add(model.student);
        // model.student is in state Added in the context
        // but the courses still have the state Unchanged.
        // Without the attach-loop above they would be in
        // state Added as well, which will create new courses
        // in the DB after SaveChanges

        db.SaveChanges();

        return RedirectToAction("Index");  
    }
    return View(model);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...