2010-11-23 1 views
87

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

Пусть у меня есть 3 таблицы

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

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

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

ответ

113

В терминах сущностей (или объектов) у вас есть 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. Проверьте this similar question.

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

Так как студенты уже находятся в базе данных, они выиграли 't будет вставлен, но поскольку они теперь находятся в коллекции StudentsClass, две записи будут вставлены в таблицу StudentClass.

+0

Привет, Спасибо за ваш ответ. Мой сценарий заключается в том, что мне нужно вставить 1 запись в класс и как x ваш пример 2 записи в StudentClass и не войти в Student. Я смущен, как я это делаю – user9969 2010-11-23 11:54:49

+0

ТО, ЧТО РАБОТАЕТ ЛЕЧЕНИЕ . Относительно обновления. Мне нужно что-то особенное, EG. Просто обновляя className, например. – user9969 2010-11-23 13:50:18

+0

Не знаете, что вы подразумеваете под `есть ли что-нибудь особенное, что мне нужно? ... Да, вы можете обновить имя и добавить/удалить элементы в/из коллекции учеников. Просто убедитесь, что вы не меняете `Id`. Если у вас есть особые проблемы с обновлением, не стесняйтесь публиковать сценарий здесь как комментарий, и я посмотрю. – Yakimych 2010-11-23 13:53:50

1

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

31

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

[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")) в том же контексте, в котором вы хотите сделать добавление.

0

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

Так вставки:.

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(); 
     } 
    } 
} 
Смежные вопросы