Insérer / mettre à jour plusieurs à plusieurs Entity Framework. Comment dois-je faire?

J'utilise EF4 et nouveau. J'ai beaucoup à beaucoup dans mon projet et ne peut pas sembler travailler sur la façon d'insérer ou de mettre à jour. J'ai construit un petit projet juste pour voir comment il devrait être codé.

Supposons que j'ai 3 tables

  1. Classe: ClassID-ClassName
  2. Étudiant: StudentID-Prénom-Nom De Famille
  3. StudentClass: StudentID-ClassID

Après avoir ajouté toute la relation et mis à jour le modèle via le navigateur de modèle, j'ai remarqué que StudentClass ne le fait pas apparaissent, cela semble être un comportement par défaut.

Maintenant, je dois faire à la fois une insertion et une mise à jour. Comment voulez-vous faire? Des exemples de code ou un lien où je peux télécharger un exemple, ou pouvez-vous épargner 5 minutes?

93
demandé sur abatishchev 2010-11-23 08:48:57

5 réponses

, En termes d'entités (ou des objets), vous avez une Class objet qui possède une collection de Students et a Student objet qui a une collection de Classes. Étant donné que votre table StudentClass ne contient que les ID et aucune information supplémentaire, EF ne génère pas d'entité pour la table de jointure. C'est le bon comportement et c'est ce que vous attendez.

Maintenant, lorsque vous faites des insertions ou des mises à jour, essayez de penser en termes d'objets. Par exemple, si vous voulez insérer une classe avec deux étudiants, créez l'objet Class, le Student objets, ajouter les étudiants à la classe Students collection ajouter l'objet Class au contexte et appeler 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();
}

Cela créera une entrée dans la table Class, Deux entrées dans la table Student et deux entrées dans la table StudentClass les reliant ensemble.

Vous faites essentiellement la même chose pour les mises à jour. Récupérez simplement les données, modifiez le graphique en ajoutant et en supprimant des objets des collections, appelez SaveChanges. Vérifiez cette question similaire pour détail.

Modifier :

Selon votre commentaire, vous devez insérer un nouveau Class et y ajouter deux Students existants:

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

Comme les deux étudiants sont déjà dans la base de données, ils ne seront pas insérés, mais comme ils sont maintenant dans la collection Students de la Class, Deux entrées seront insérées dans la table StudentClass.

125
répondu Yakimych 2017-05-23 12:10:43

Essayez celui-ci pour la mise à jour:

[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
répondu Stritof 2013-01-22 13:54:55

Je voulais ajouter mon expérience. En effet EF, lorsque vous ajoutez un objet au contexte, il change L'état de tous les enfants et entités associées à Ajouté. Bien qu'il y ait une petite exception dans la règle ici: si les enfants/entités liées sont suivis par le même contexte, EF comprend que ces entités existent et ne les ajoute pas. Le problème se produit lorsque, par exemple, vous chargez les enfants / entités associées à partir d'un autre contexte ou d'une interface utilisateur web, etc., puis Oui, EF ne sait rien de ces entités et va et ajoute tous. Pour éviter cela, il suffit d'obtenir les clés des entités et de les trouver (par exemple context.Students.FirstOrDefault(s => s.Name == "Alice")) dans le même contexte dans lequel vous voulez faire l'addition.

4
répondu Athina 2017-02-17 21:09:54

Dans entity framework, lorsque l'objet est ajouté au contexte, son état devient ajouté. EF change également l'état de chaque objet ajouté dans l'arborescence des objets et vous obtenez donc une erreur de violation de clé primaire ou des enregistrements en double sont ajoutés dans la table.

1
répondu Nilesh Hirapra 2012-03-05 18:44:21

J'utilise la manière suivante pour gérer la relation plusieurs à plusieurs où seules les clés étrangères sont impliquées.

Donc, pour insertion:

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

Pour suppression de,

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
répondu tooatui 2017-11-06 05:16:25