Asp.net mvc 实体框架多对多关系添加了;完";添加关系之前的项目

Asp.net mvc 实体框架多对多关系添加了;完";添加关系之前的项目,asp.net-mvc,entity-framework,Asp.net Mvc,Entity Framework,我已经建立了一个非常简单的实体框架数据库第一个项目,使用普通学生和课程场景 一个学生可以有很多课程 一门课程可以有很多学生 我已经在数据库中建立了关系,EF为此创建了一个很好的多对多导航项 问题当我向学生添加课程时,课程会重新添加到课程表中,然后关系会添加到数据库中,导致重复课程的数量不断增加 这让我快发疯了,知道我做错了什么吗 我的一些代码 我在实体生成的基础上创建了一个分部类,这样我就可以有一个带有复选框的EditorTemplate,这将允许用户勾选要添加的课程 public part

我已经建立了一个非常简单的实体框架数据库第一个项目,使用普通学生和课程场景

  • 一个学生可以有很多课程
  • 一门课程可以有很多学生
我已经在数据库中建立了关系,EF为此创建了一个很好的多对多导航项

问题当我向学生添加课程时,课程会重新添加到课程表中,然后关系会添加到数据库中,导致重复课程的数量不断增加

这让我快发疯了,知道我做错了什么吗

我的一些代码

我在实体生成的基础上创建了一个分部类,这样我就可以有一个带有复选框的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; }
}
如果您能为我指出正确的方向,我们将不胜感激。

在将学生添加到上下文之前,您必须在您的post操作中将所选课程附加到上下文中。否则,EF假设整个对象图(包括所有课程的学生)是新的,必须插入到数据库中。通过附加(=将课程置于<代码>未更改状态),您告诉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);
}

听起来很有道理,我会在周一试一试!非常感谢。
@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>
}
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);
}
[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);
}