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

发布于 2024-10-04 06:21:41 字数 347 浏览 1 评论 0原文

我正在使用 EF4,而且是新手。我的项目中有多对多,似乎无法弄清楚如何插入或更新。我构建了一个小项目只是为了看看应该如何编码。

假设我有 3 个表

  1. Class : ClassID-ClassName
  2. Student : StudentID-FirstName-Surname
  3. StudentClass : StudentID-ClassID

添加所有关系并通过模型浏览器更新模型后,我注意到 StudentClass 没有出现,这似乎是默认行为。

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

I'm using EF4 and new to it. I have a many to many in my project and cannot seem to work out how to insert or update. I have build a small project just to see how it should be coded.

Suppose I have 3 tables

  1. Class : ClassID-ClassName
  2. Student : StudentID-FirstName-Surname
  3. StudentClass : StudentID-ClassID

After adding all the relationship and updated the model via model browser I have noticed that StudentClass does not appear, this seems to be default behaviour.

Now I need to do both an Insert and Update. How do you do it? Any code samples or link where I can download an example, or can you spare 5 mins?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

明月松间行 2024-10-11 06:21:41

就实体(或对象)而言,您有一个 Class 对象,其中包含 Students 的集合,以及一个 Student 对象,其中包含 Students 的集合代码>类。由于您的 StudentClass 表仅包含 Id,没有额外信息,因此 EF 不会为连接表生成实体。这是正确的行为,也是您所期望的。

现在,在进行插入或更新时,请尝试从对象的角度进行思考。例如,如果您想插入一个有两名学生的班级,请创建 Class 对象、Student 对象,将学生添加到班级 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();
}

这将在 Class 表中创建一个条目,在 Student 中创建两个条目 表和 StudentClass 表中的两个条目将它们链接在一起。

您基本上对更新执行相同的操作。只需获取数据,通过在集合中添加和删除对象来修改图表,调用 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();
}

因为两个学生都已经在数据库中,它们不会被插入,但由于它们现在位于 ClassStudents 集合中,因此两个条目将被插入到 StudentClass 中> 表。

In terms of entities (or objects) you have a Class object which has a collection of Students and a Student object that has a collection of Classes. Since your StudentClass table only contains the Ids and no extra information, EF does not generate an entity for the joining table. That is the correct behaviour and that's what you expect.

Now, when doing inserts or updates, try to think in terms of objects. E.g. if you want to insert a class with two students, create the Class object, the Student objects, add the students to the class Students collection add the Class object to the context and call 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();
}

This will create an entry in the Class table, two entries in the Student table and two entries in the StudentClass table linking them together.

You basically do the same for updates. Just fetch the data, modify the graph by adding and removing objects from collections, call SaveChanges. Check this similar question for details.

Edit:

According to your comment, you need to insert a new Class and add two existing Students to it:

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();
}

Since both students are already in the database, they won't be inserted, but since they are now in the Students collection of the Class, two entries will be inserted into the StudentClass table.

静若繁花 2024-10-11 06:21:41

尝试这个更新:

[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);
}

Try this one for Updating:

[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);
}
爱格式化 2024-10-11 06:21:41

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

因此,对于插入

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();
    }
}

对于删除

public void DeleteStudentClass(long studentId, long classId)
{
    Student student = context.Students.Include(x => x.Classes).Single(x => x.StudentID == studentId);

    using (var context = new DatabaseContext())
    {
        context.Students.Attach(student);
        Class classToDelete = student.Classes.Find(x => x.ClassID == classId);
        if (classToDelete != null)
        {
            student.Classes.Remove(classToDelete);
            context.SaveChanges();
        }
    }
}

I use the following way to handle the many-to-many relationship where only foreign keys are involved.

So for inserting:

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();
    }
}

For deleting,

public void DeleteStudentClass(long studentId, long classId)
{
    Student student = context.Students.Include(x => x.Classes).Single(x => x.StudentID == studentId);

    using (var context = new DatabaseContext())
    {
        context.Students.Attach(student);
        Class classToDelete = student.Classes.Find(x => x.ClassID == classId);
        if (classToDelete != null)
        {
            student.Classes.Remove(classToDelete);
            context.SaveChanges();
        }
    }
}
愿得七秒忆 2024-10-11 06:21:41

我想在这方面补充我的经验。事实上,EF 中,当您将一个对象添加到上下文时,它会将所有子实体和相关实体的状态更改为“已添加”。尽管这里的规则有一个小例外:如果子实体/相关实体由同一上下文跟踪,则 EF 确实知道这些实体存在并且不会添加它们。例如,当您从其他上下文或 Web UI 等加载子实体/相关实体,然后是的,EF 不知道有关这些实体的任何信息并添加所有实体时,就会出现问题。为了避免这种情况,只需获取实体的键并在您所在的同一上下文中找到它们(例如 context.Students.FirstOrDefault(s => s.Name == "Alice"))想做加法。

I wanted to add my experience on that. Indeed EF, when you add an object to the context, it changes the state of all the children and related entities to Added. Although there is a small exception in the rule here: if the children/related entities are being tracked by the same context, EF does understand that these entities exist and doesn't add them. The problem happens when for example, you load the children/related entities from some other context or a web ui etc and then yes, EF doesn't know anything about these entities and goes and adds all of them. To avoid that, just get the keys of the entities and find them (e.g. context.Students.FirstOrDefault(s => s.Name == "Alice")) in the same context in which you want to do the addition.

心凉怎暖 2024-10-11 06:21:41

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

In entity framework, when object is added to context, its state changes to Added. EF also changes state of each object to added in object tree and hence you are either getting primary key violation error or duplicate records are added in table.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文