Entity Framework: enregistrements en double dans une relation plusieurs à plusieurs

J’ai le premier code de entity framework suivant. Les tables sont créées et les données sont insérées. Cependant, il y a des enregistrements en double dans la table Club.

Mes opérations sont: –

  1. Créer des clubs en utilisant l’application de création de club

  2. Créer des personnes à l’aide d’une application personnelle

Comment éviter les doublons?

entrez la description de l'image ici

static void Main(ssortingng[] args) { Database.SetInitializer(new MyInitializer()); CreateClubs(); InsertPersons(); } public static void CreateClubs() { ssortingng connectionssortingng = "Data Source=.;Initial Catalog=NerdDinners;Integrated Security=True;Connect Timeout=30"; using (var db = new NerdDinners(connectionssortingng)) { Club club1 = new Club(); club1.ClubName = "club1"; Club club2 = new Club(); club2.ClubName = "club2"; Club club3 = new Club(); club3.ClubName = "club3"; db.Clubs.Add(club1); db.Clubs.Add(club2); db.Clubs.Add(club3); int recordsAffected = db.SaveChanges(); } } public static Club GetClubs(ssortingng clubName) { ssortingng connectionssortingng = "Data Source=.;Initial Catalog=NerdDinners;Integrated Security=True;Connect Timeout=30"; using (var db = new NerdDinners(connectionssortingng)) { //var query = db.Clubs.Where(p => p.ClubName == clubName); var query = db.Clubs.SingleOrDefault(p => p.ClubName == clubName); return query; } } public static void InsertPersons() { ssortingng connectionssortingng = "Data Source=.;Initial Catalog=NerdDinners;Integrated Security=True;Connect Timeout=30"; using (var db = new NerdDinners(connectionssortingng)) { Club club1 = GetClubs("club1"); Club club2 = GetClubs("club2"); Club club3 = GetClubs("club3"); Person p1 = new Person(); p1.PersonName = "Person1"; Person p2 = new Person(); p2.PersonName = "Person2"; List clubsForPerson1 = new List(); clubsForPerson1.Add(club1); clubsForPerson1.Add(club3); List clubsForPerson2 = new List(); clubsForPerson2.Add(club2); clubsForPerson2.Add(club3); p1.Clubs = clubsForPerson1; p2.Clubs = clubsForPerson2; db.Persons.Add(p1); db.Persons.Add(p2); int recordsAffected = db.SaveChanges(); } } 

Domaine

 public class Person { public int PersonId { get; set; } public ssortingng PersonName { get; set; } public virtual ICollection Clubs { get; set; } } public class Club { public int ClubId { get; set; } public ssortingng ClubName { get; set; } public virtual ICollection Members { get; set; } } //System.Data.Entity.DbContext is from EntityFramework.dll public class NerdDinners : System.Data.Entity.DbContext { public NerdDinners(ssortingng connSsortingng): base(connSsortingng) { } protected override void OnModelCreating(DbModelBuilder modelbuilder) { //Fluent API - Plural Removal modelbuilder.Conventions.Remove(); } public DbSet Persons { get; set; } public DbSet Clubs { get; set; } } 

Le problème est que vous créez plus de contextes.

D’abord, vous créez les clubs. C’est bon. Mais lorsque vous créez les personnes, vous récupérez les clubs via GetClubs , mais pour chaque club, vous disposez du contexte de l’entité lui-même afin de créer des entités détachées. Dans InsertPersons vous ajoutez des entités de club détachées aux nouvelles personnes afin que le contexte actuel pense que les clubs sont de nouveaux clubs.

Ainsi, lorsque vous ajoutez un club à une personne, vous créez de nouveaux clubs.

Cela est dû au fait que la structure d’entités suit les modifications et gère les entités par contexte. Si vous ajoutez une entité à un contexte qui ne la contient pas encore, elle sera traitée comme une nouvelle entité.

En fait, vous devriez faire quelque chose comme ça (non testé):

 static void Main(ssortingng[] args) { Database.SetInitializer(new MyInitializer()); ssortingng connectionssortingng = "Data Source=.;Initial Catalog=NerdDinners;Integrated Security=True;Connect Timeout=30"; using (var db = new NerdDinners(connectionssortingng)) { CreateClubs(db); InsertPersons(db); } } public static void CreateClubs(NerdDinners db) { Club club1 = new Club(); club1.ClubName = "club1"; Club club2 = new Club(); club2.ClubName = "club2"; Club club3 = new Club(); club3.ClubName = "club3"; db.Clubs.Add(club1); db.Clubs.Add(club2); db.Clubs.Add(club3); int recordsAffected = db.SaveChanges(); } public static Club GetClubs(ssortingng clubName, NerdDinners db) { //var query = db.Clubs.Where(p => p.ClubName == clubName); var query = db.Clubs.SingleOrDefault(p => p.ClubName == clubName); return query; } public static void InsertPersons(NerdDinners db) { Club club1 = GetClubs("club1", db); Club club2 = GetClubs("club2", db); Club club3 = GetClubs("club3", db); Person p1 = new Person(); p1.PersonName = "Person1"; Person p2 = new Person(); p2.PersonName = "Person2"; List clubsForPerson1 = new List(); clubsForPerson1.Add(club1); clubsForPerson1.Add(club3); List clubsForPerson2 = new List(); clubsForPerson2.Add(club2); clubsForPerson2.Add(club3); p1.Clubs = clubsForPerson1; p2.Clubs = clubsForPerson2; db.Persons.Add(p1); db.Persons.Add(p2); int recordsAffected = db.SaveChanges(); } 

Bien sûr, vous devriez reformuler la structure de ce code, mais veuillez noter que je n’utilise qu’un seul contexte EF pour mes opérations.

Merci à PeterPorfy

Lisez également l’ exception de type ‘System.ObjectDisposedException’

j’ai utilisé

  ((IObjectContextAdapter)db).ObjectContext.Attach((IEntityWithKey)entity); 

pour attacher les objects du contexte précédent.

Un exemple pour IEntityWithKey que j’ai utilisé est le suivant. Veuillez commenter si vous voyez un problème avec cette approche.

 public class Person : IEntityWithKey { public int PersonId { get; set; } public ssortingng PersonName { get; set; } public EntityKey EntityKey { get; set; } } 

S’il vous plaît se référer à ce qui suit aussi

  1. Problème avec SaveChanges () Entity Framework 4.1
  2. Entity Framework Mise à jour de relations plusieurs à plusieurs – POCO