Вставка / обновление многих для многих Entity Framework. Как мне это сделать?

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

Предположим, у меня есть 3 таблицы

  1. Класс: ClassID-ClassName
  2. Студент : StudentID-Имя-Фамилия
  3. StudentClass: StudentID-ClassID

после добавления всех отношений и обновления модели через браузер моделей у меня есть заметил, что StudentClass не появляется, это похоже на поведение по умолчанию.

теперь мне нужно сделать как Insert и Update. Как вы это делаете? Любые примеры кода или ссылка, где я могу скачать пример, или вы можете сэкономить 5 минут?

5 ответов


в терминах сущностей (или объектов) у вас есть Class объект, который имеет коллекцию Students и a Student объект, который имеет коллекцию Classes. С вашего StudentClass таблица содержит только идентификаторы и никакой дополнительной информации, 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);
}

Я хотел добавить свой опыт в этом. Действительно, EF, когда вы добавляете объект в контекст, он изменяет состояние всех дочерних и связанных сущностей на Added. Хотя в правиле здесь есть небольшое исключение: если дочерние/связанные сущности отслеживаются одним и тем же контекстом, EF понимает, что эти сущности существуют и не добавляет их. Проблема возникает, когда, например, вы загружаете дочерние / связанные сущности из другого контекста или веб-интерфейса и т. д., а затем да, EF ничего не знает об этих сущностях и добавляет их все. Чтобы избежать этого, просто получите ключи сущностей и найдите их (например,context.Students.FirstOrDefault(s => s.Name == "Alice")) в том же контексте, в котором вы хотите сделать дополнение.


в entity framework при добавлении объекта в контекст его состояние изменяется на Added. EF также изменяет состояние каждого объекта на добавленное в дереве объектов, и, следовательно, вы получаете ошибку нарушения первичного ключа или дубликаты записей добавляются в таблицу.


Я использую следующий способ обработки отношений "многие ко многим", в которых задействованы только внешние ключи.

и вставка:

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