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

  1. Class: ClassID-className
  2. Student: StudentID-FirstName-Surname
  3. 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?

Author: abatishchev, 2010-11-23

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.

 125
Author: Yakimych,
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);
}
 36
Author: Stritof,
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.

 4
Author: Athina,
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.

 1
Author: Nilesh Hirapra,
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();
        }
    }
}
 1
Author: tooatui,
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