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: –
Créer des clubs en utilisant l’application de création de club
Créer des personnes à l’aide d’une application personnelle
Comment éviter les doublons?
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