简体   繁体   English

实体框架:插入多对多关系

[英]Entity Framework: insert into a many-to-many relationship

Why A and B in a many-to-many relationship, when inserting record to A table, a new record will be added in B table as well? 为什么将A和B以多对多的关系将记录插入A表时,也会在B表中添加一条新记录?

There are two model classes, Customer and Course . 有两个模型类, CustomerCourse One customer can choose many courses. 一个客户可以选择许多课程。 Also, one course can be chosen by many customers. 同样,许多客户可以选择一门课程。

The problem I met is that when I create a customer with some courses he selected (for example course1 and course2 ), course1 and course2 are already in the Courses table, but it will automatically insert course1 and course2 again which is not what I want. 我遇到的问题是,当我创建一个客户并course2选择了一些课程(例如course1course2 )时, course1course2已经在Courses表中,但是它将自动再次插入course1course2 ,这不是我想要的。

Customer class: 客户类别:

public class Customer
{
    public int Id { get; set; }

    [MaxLength(20)]
    public string City { get; set; }

    [Range(16,58)]
    public int  Age { get; set; }
    public Gender Gender { get; set; }

    [MaxLength(20)]
    public string Name { get; set; }

    public IList<Course> CoursesEnrolled { get; set; }
}

Course class: 课程类别:

public class Course
{
    public int  Id { get; set; }

    [MaxLength(50)] 
    [Required]
    public string Name { get; set; }
}

CustomerController , Save method: CustomerControllerSave方法:

[HttpPost]
public ActionResult Save( Customer customer 
{
        if (customer.Id == 0)
        {
            Customer customerInDb = new Customer()
            {
                Name = customer.Name , 
                City = customer.City ,
                Age = customer.Age ,
                Gender = customer.Gender ,
                CoursesEnrolled =  customer.CoursesEnrolled 
            };

            _context.Customers.Add(customerInDb);
        }
        else
        {
            var customerInDb = _context.Customers.SingleOrDefault(c => c.Id == customer.Id);

            if (customerInDb == null)
            {
                return HttpNotFound();
            }

            customerInDb.Name = customer.Name;
            customerInDb.Age = customer.Age;
            customerInDb.City = customer.City;
            customerInDb.Gender = customer.Gender;
            customerInDb.CoursesEnrolled = customer.CoursesEnrolled;
        }

        try
        {
            _context.SaveChanges();
        }
        catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
        {
            Exception raise = dbEx;

            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                foreach (var validationError in validationErrors.ValidationErrors)
                {
                    string message = string.Format("{0}:{1}",
                        validationErrors.Entry.Entity.ToString(),
                        validationError.ErrorMessage);
                    raise = new InvalidOperationException(message, raise);
                }
            }

            throw raise;
        }

        return RedirectToAction("Index" , "Customer");
}

Four courses exist in the Courses table: Courses表中存在四个课程:

enter image description here 在此处输入图片说明

When I create a customer with some courses selected, Customer saves successfully, and CustomersCourses also added the data. 当我创建一个选择了某些课程的客户时, Customer保存成功,并且CustomersCourses也添加了数据。

But in the Courses table, the selecting courses that the customer enrolled also are added to the courses table. 但是,在“ Courses表”中,客户注册的所选课程也会添加到课程表中。

enter image description here 在此处输入图片说明

The data in the red triangle is not we want. 红色三角形中的数据不是我们想要的。

Any help or suggestions would be appreciated, thanks! 任何帮助或建议,将不胜感激,谢谢!

I think you use new instances of Courses (with the same ID as that of the persisted record in the database) every time a new Customer instance is created. 我认为您每次创建新的Customer实例时都使用Courses的新实例(具有与数据库中持久记录相同的ID)。 EF tracks them as a newly added objects and inserts them to db as new records on save changes. EF将它们作为新添加的对象进行跟踪,并将它们作为保存更改时的新记录插入db。 There are a couple of options: 有两种选择:

  1. Load Courses from the context and add them to the CoursesEnrolled collection of the customer instance, which lets EF know that the entity is already persisted in the database. 从上下文中加载课程,并将其添加到客户实例的CoursesEnrolled集合中,该集合使EF知道该实体已经保留在数据库中。

  2. Explcitly mark the CoursesEnrolled as Unchanged/Detached so that EF would skip it. 将“已注册的课程”标记为“未更改/已取消”,以便EF跳过它。

     foreach (var course in customerInDb.CoursesEnrolled) { _context.Entry(course).State = System.Data.Entity.EntityState.Unchanged; } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM