Вставить / обновить многие для многих Entity Framework . Как мне это сделать?
Я использую EF4 и новичок в этом. У меня есть много ко многим в моем проекте, и я не могу понять, как вставить или обновить. Я создал небольшой проект, чтобы посмотреть, как он должен быть закодирован.
Предположим, у меня есть 3 таблицы
- Класс: ClassID-ClassName
- Студент: StudentID-Имя-Фамилия
- Студенческий класс: StudentID-ClassID
После добавления всех отношений и обновления модели через браузер модели я заметил, что StudentClass не отображается, это поведение по умолчанию.
Теперь мне нужно сделать обе вставки и обновления. Как ты делаешь это? Любые примеры кода или ссылку, где я могу скачать пример, или вы можете сэкономить 5 минут?
5 ответов
С точки зрения сущностей (или объектов) у вас есть 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
, Проверьте этот похожий вопрос для деталей.
Редактировать:
Согласно вашему комментарию, вам необходимо вставить новый 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
Таблица.
Попробуйте это для обновления:
[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);
}
Я использую следующий способ обработки отношения "многие ко многим", когда задействованы только внешние ключи.
Итак, для вставки:
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();
}
}
}
Я хотел добавить свой опыт в этом. Действительно, EF, когда вы добавляете объект в контекст, он изменяет состояние всех дочерних и связанных сущностей на Добавленный. Хотя в этом правиле есть небольшое исключение: если дочерние / связанные сущности отслеживаются в одном и том же контексте, EF понимает, что эти сущности существуют, и не добавляет их. Проблема возникает, когда, например, вы загружаете дочерние / связанные сущности из какого-либо другого контекста или веб-интерфейса и т. Д., А затем да, EF ничего не знает об этих сущностях и идет и добавляет их все. Чтобы избежать этого, просто получите ключи сущностей и найдите их (например, context.Students.FirstOrDefault(s => s.Name == "Alice"))
в том же контексте, в котором вы хотите сделать сложение.
В каркасе сущностей, когда объект добавляется в контекст, его состояние изменяется на "Добавлен". EF также изменяет состояние каждого объекта на добавляемое в дерево объектов, и, следовательно, вы либо получаете ошибку нарушения первичного ключа, либо дублирующиеся записи добавляются в таблицу.