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

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

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

  • Класс: ClassID-ClassName
  • Студент: StudentID-FirstName-Surname
  • StudentClass: StudentID-ClassID

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

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

Ответ 1

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

Edit

В соответствии с вашим комментарием вам нужно вставить новый Class и добавить к нему два существующих Students:

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

Поскольку оба ученика уже находятся в базе данных, они не будут вставлены, но поскольку они теперь находятся в коллекции Students Class, две записи будут вставлены в таблицу StudentClass.

Ответ 2

Попробуйте этот вариант для обновления:

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

Ответ 3

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

Ответ 4

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

Ответ 5

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

Итак, для вставки:

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