c# - remove - Insertar/actualizar muchos a muchos marcos de entidades. ¿Cómo lo hago?
update collection entity framework (5)
Estoy usando EF4 y nuevo en esto. Tengo muchos para muchos en mi proyecto y parece que no puedo resolver cómo insertar o actualizar. Construí un pequeño proyecto solo para ver cómo debería codificarse.
Supongamos que tengo 3 tablas
- Clase: ClassID-ClassName
- Estudiante: StudentID-FirstName-Apellido
- StudentClass: StudentID-ClassID
Después de agregar toda la relación y actualizar el modelo a través del navegador de modelos, noté que StudentClass no aparece, esto parece ser un comportamiento predeterminado.
Ahora necesito hacer un Insert y una actualización. ¿Cómo lo haces? ¿Alguna muestra de código o enlace donde pueda descargar un ejemplo, o puede dedicar 5 minutos?
En el marco de la entidad, cuando se agrega un objeto al contexto, su estado cambia a Agregado. EF también cambia el estado de cada objeto para agregarlo en el árbol de objetos y, por lo tanto, obtiene un error de violación de clave principal o se agregan registros duplicados en la tabla.
Pruebe este para la Actualización:
[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);
}
Utilizo la siguiente forma para manejar la relación muchos a muchos donde solo están involucradas claves externas.
Entonces para insertar :
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();
}
}
Para eliminar ,
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();
}
}
}
Yo quería agregar mi experiencia en eso. Efectivamente EF, cuando agrega un objeto al contexto, cambia el estado de todos los elementos secundarios y entidades relacionadas a Added. Aunque hay una pequeña excepción en la regla aquí: si los niños / entidades relacionadas están siendo rastreados por el mismo contexto, EF entiende que estas entidades existen y no las agrega. El problema ocurre cuando, por ejemplo, cargas los elementos secundarios / entidades relacionadas desde otro contexto o una interfaz web, etc. y luego sí, EF no sabe nada sobre estas entidades y va y las agrega todas. Para evitar eso, simplemente obtenga las claves de las entidades y encuéntrelas (por ejemplo, context.Students.FirstOrDefault(s => s.Name == "Alice"))
en el mismo contexto en el que desea hacer la adición.
En términos de entidades (u objetos), tiene un objeto de Class
que tiene una colección de Students
y un objeto de Student
que tiene una colección de Classes
. Como su tabla StudentClass solo contiene los Id. Y no hay información adicional, EF no genera una entidad para la tabla de unión. Ese es el comportamiento correcto y eso es lo que esperas.
Ahora, al hacer inserciones o actualizaciones, intente pensar en términos de objetos. Por ejemplo, si desea insertar una clase con dos alumnos, cree el objeto de Class
, los objetos de Student
, agregue los alumnos a la clase, colección de Students
, agregue el objeto de Class
al contexto y llame a 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();
}
Esto creará una entrada en la tabla de Class
, dos entradas en la tabla de Student
y dos entradas en la tabla de Class
StudentClass
uniéndolos.
Básicamente haces lo mismo para las actualizaciones. Simplemente busque los datos, modifique el gráfico agregando y quitando objetos de las colecciones, llame a SaveChanges
. Verifique esta pregunta similar para más detalles.
Editar :
Según su comentario, debe insertar una nueva Class
y agregarle dos Students
existentes:
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();
}
Dado que ambos estudiantes ya están en la base de datos, no se insertarán, pero dado que ahora están en la colección de Students
de la Class
, se insertarán dos entradas en la tabla StudentClass
.