C# 插入/更新多对多实体框架。我该怎么做?

C# 插入/更新多对多实体框架。我该怎么做?,c#,entity-framework,many-to-many,C#,Entity Framework,Many To Many,我正在使用EF4和新的。我在我的项目中有一个多对多,似乎无法解决如何插入或更新。我已经建立了一个小项目,只是为了看看它应该如何编码 假设我有3张桌子 类:ClassID类名称 学生:学生姓名 StudentClass:StudentID ClassID 添加所有关系并通过模型浏览器更新模型后,我注意到StudentClass没有出现,这似乎是默认行为 现在我需要同时进行插入和更新。你是怎么做到的?任何我可以下载示例的代码示例或链接,或者您可以抽出5分钟的时间吗?就实体(或对象)而言,您有一个类对

我正在使用EF4和新的。我在我的项目中有一个多对多,似乎无法解决如何插入或更新。我已经建立了一个小项目,只是为了看看它应该如何编码

假设我有3张桌子

  • 类:ClassID类名称
  • 学生:学生姓名
  • StudentClass:StudentID ClassID
  • 添加所有关系并通过模型浏览器更新模型后,我注意到StudentClass没有出现,这似乎是默认行为

    现在我需要同时进行插入和更新。你是怎么做到的?任何我可以下载示例的代码示例或链接,或者您可以抽出5分钟的时间吗?

    就实体(或对象)而言,您有一个
    对象,它有一个
    学生的集合
    和一个
    学生的
    对象,它有一个
    类的集合
    。由于您的
    StudentClass
    表只包含ID,没有额外信息,因此EF不会为联接表生成实体。这是正确的行为,也是你所期望的

    现在,在执行插入或更新时,请尝试从对象的角度来考虑。例如,如果要插入一个包含两个学生的类,请创建
    class
    对象
    Student
    对象,将学生添加到class
    students
    集合将
    class
    对象添加到上下文中,并调用
    SaveChanges

    using (var context = new YourContext())
    {
        var mathClass = new Class { Name = "Math" };
        mathClass.Students.Add(new Student { Name = "Alice" });
        mathClass.Students.Add(new Student { Name = "Bob" });
    
        context.AddToClasses(mathClass);
        context.SaveChanges();
    }
    
    这将在
    表中创建一个条目,在
    学生
    表中创建两个条目,在
    学生类
    表中创建两个条目,将它们链接在一起

    对于更新,您基本上也是这样做的。只需获取数据,通过添加和删除集合中的对象来修改图形,调用
    SaveChanges
    。查看详细信息

    编辑

    public void InsertStudentClass (long studentId, long classId)
    {
        using (var context = new DatabaseContext())
        {
            Student student = new Student { StudentID = studentId };
            context.Students.Add(student);
            context.Students.Attach(student);
    
            Class class = new Class { ClassID = classId };
            context.Classes.Add(class);
            context.Classes.Attach(class);
    
            student.Classes = new List<Class>();
            student.Classes.Add(class);
    
            context.SaveChanges();
        }
    }
    
    根据您的评论,您需要插入一个新的
    ,并向其中添加两个现有的
    学生

    using (var context = new YourContext())
    {
        var mathClass= new Class { Name = "Math" };
        Student student1 = context.Students.FirstOrDefault(s => s.Name == "Alice");
        Student student2 = context.Students.FirstOrDefault(s => s.Name == "Bob");
        mathClass.Students.Add(student1);
        mathClass.Students.Add(student2);
    
        context.AddToClasses(mathClass);
        context.SaveChanges();
    }
    

    由于两个学生都已在数据库中,因此不会插入他们,但由于他们现在在
    类的
    学生
    集合中,两个条目将插入
    学生类
    表中。

    在实体框架中,当对象添加到上下文中时,其状态更改为added。EF还将每个对象的状态更改为添加到对象树中,因此您将获得主键冲突错误或在表中添加重复记录。

    尝试此更新:

    [HttpPost]
    public ActionResult Edit(Models.MathClass mathClassModel)
    {
        //get current entry from db (db is context)
        var item = db.Entry<Models.MathClass>(mathClassModel);
    
        //change item state to modified
        item.State = System.Data.Entity.EntityState.Modified;
    
        //load existing items for ManyToMany collection
        item.Collection(i => i.Students).Load();
    
        //clear Student items          
        mathClassModel.Students.Clear();
    
        //add Toner items
        foreach (var studentId in mathClassModel.SelectedStudents)
        {
            var student = db.Student.Find(int.Parse(studentId));
            mathClassModel.Students.Add(student);
        }                
    
        if (ModelState.IsValid)
        {
           db.SaveChanges();
           return RedirectToAction("Index");
        }
    
        return View(mathClassModel);
    }
    
    [HttpPost]
    公共操作结果编辑(Models.MathClass mathClassModel)
    {
    //从数据库获取当前条目(数据库是上下文)
    var item=db.Entry(mathClassModel);
    //将项目状态更改为“已修改”
    item.State=System.Data.Entity.EntityState.Modified;
    //加载多个集合的现有项
    item.Collection(i=>i.Students.Load();
    //清除学生项目
    mathClassModel.Students.Clear();
    //添加碳粉项目
    foreach(mathClassModel中的var studentId.SelectedStudents)
    {
    var student=db.student.Find(int.Parse(studentId));
    mathClassModel.Students.Add(学生);
    }                
    if(ModelState.IsValid)
    {
    db.SaveChanges();
    返回操作(“索引”);
    }
    返回视图(mathClassModel);
    }
    
    我想增加我在这方面的经验。实际上,当您向上下文添加对象时,它会将所有子对象和相关实体的状态更改为“已添加”。尽管这里的规则中有一个小的例外:如果子实体/相关实体被同一上下文跟踪,EF知道这些实体存在,并且不添加它们。例如,当您从其他上下文或web ui等加载子实体/相关实体,然后是的,EF对这些实体一无所知,并将它们全部添加时,就会出现问题。为了避免这种情况,只需获取实体的键并在要进行加法的同一上下文中找到它们(例如,
    context.Students.FirstOrDefault(s=>s.Name==“Alice”)

    我使用以下方法处理只涉及外键的多对多关系

    因此,对于插入:

    public void InsertStudentClass (long studentId, long classId)
    {
        using (var context = new DatabaseContext())
        {
            Student student = new Student { StudentID = studentId };
            context.Students.Add(student);
            context.Students.Attach(student);
    
            Class class = new Class { ClassID = classId };
            context.Classes.Add(class);
            context.Classes.Attach(class);
    
            student.Classes = new List<Class>();
            student.Classes.Add(class);
    
            context.SaveChanges();
        }
    }
    

    你好谢谢你的回复。我的情况是,我需要在类中插入1个条目,而在StudentClass中插入2个条目,而在StudentClass中没有条目。我很困惑我是如何做到这一点的。关于更新。我需要做什么特别的事吗?例如,只是更新类名。这将增加获取的开销从数据库中选择需要添加的项。Attach方法只能用于添加关系。另请参见AddToClasses是类的DbSet?不要忘记在类和学生的构造函数中初始化集合。例如:public Class(){this.Students=new HashSet();}这节省了我的时间谢谢!!!它们的关键部分是item.Collection(i=>i.Students.Load();部分只是旁注,我在做这件事时遇到了一个InvalidOperationException,比如我的实体在上下文中不存在。我刚刚调用context.MyEntityCollection.Attach(myEntity)来处理它。考虑到问题是插入和更新,这个答案完成了问题和已接受的答案。非常感谢你!所以mathClassModel有两个集合,Students有它的实体,SelectedStudents只有它的ID,为什么?实体框架是否像只有一个ChildId和子实体时那样自动映射它们?我不这么认为