Insertar / Actualizar Muchos a Muchos Entity Framework. ¿Cómo lo hago?
Estoy usando EF4 y soy nuevo en él. Tengo muchos a muchos en mi proyecto y parece que no puedo encontrar la manera de insertar o actualizar. He construido un pequeño proyecto sólo para ver cómo debe ser codificado.
Supongamos que tengo 3 tablas
- Class: ClassID-className
- Student: StudentID-FirstName-Surname
- StudentClass: StudentID-ClassID
Después de agregar toda la relación y actualizar el modelo a través del navegador de modelos, he notado que StudentClass no lo hace parece, este parece ser el comportamiento por defecto.
Ahora necesito hacer una Inserción y una actualización. ¿Cómo lo haces? ¿Alguna muestra de código o enlace donde pueda descargar un ejemplo, o puede ahorrar 5 minutos?
5 answers
En términos de entidades (u objetos) tienes un objeto Class
que tiene una colección de Students
y un objeto Student
que tiene una colección de Classes
. Dado que su tabla StudentClass
solo contiene los ID y ninguna 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, trate de pensar en términos de objetos. Por ejemplo, si desea insertar una clase con dos estudiantes, cree el objeto Class
, el Student
objetos, añadir los estudiantes a la colección class Students
añadir el objeto Class
al contexto y llamar 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 Class
, dos entradas en la tabla Student
y dos entradas en la tabla StudentClass
vinculándolas entre sí.
Básicamente haces lo mismo para las actualizaciones. Simplemente obtenga los datos, modifique el gráfico agregando y eliminando objetos de colecciones, llame a SaveChanges
. Compruebe esta pregunta similar para detalles.
Edit :
De acuerdo con su comentario, debe insertar un nuevo Class
y agregar 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 ya que ahora están en la colección Students
de la Class
, dos entradas se insertarán en la tabla StudentClass
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:43
Pruebe este para actualizar:
[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);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-22 13:54:55
Quería añadir mi experiencia al respecto. De hecho EF, cuando agrega un objeto al contexto, cambia el estado de todos los hijos y entidades relacionadas a Agregado. Aunque hay una pequeña excepción en la regla aquí: si los hijos/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, carga los hijos / entidades relacionadas desde algún otro contexto o una interfaz de usuario web, etc. y luego sí, EF no sabe nada sobre estas entidades y va y agrega todas ellas. 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.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-17 21:09:54
En entity framework, cuando el objeto se agrega al contexto, su estado cambia a Agregado. EF también cambia el estado de cada objeto a agregado en el árbol de objetos y, por lo tanto, obtiene un error de violación de clave primaria o se agregan registros duplicados en la tabla.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-05 18:44:21
Utilizo la siguiente forma para manejar la relación muchos a muchos donde solo están involucradas las claves foráneas.
Así que 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();
}
}
For deleting ,
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();
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-06 05:16:25