La relation entre les deux objects ne peut pas être définie car ils sont attachés à différents objects ObjectContext

J’ai lu des questions / réponses relatives à ce message d’erreur, mais je ne comprends pas très bien la solution appropriée.

J’ai lu à plusieurs resockets que vous devriez créer le contexte EF4, l’utiliser, puis en disposer. Tout au long de mon application, je charge des entités ici et là en utilisant différents objects de contexte, puis je souhaite éventuellement les associer.

J’ai créé une application console simple qui provoque facilement l’erreur. Le modèle très simple est schématisé suivi du code.

Comment faire en sorte que les deux entités différentes partagent le même contexte? Dois-je vraiment créer un nouveau contexte, charger à nouveau les deux entités (même si je les ai déjà), simplement les associer et les sauvegarder?

Si j’ai simplement manqué une question / réponse appropriée existante, veuillez m’indiquer le bon endroit.

Schéma de modèle EF4 simple

internal class Program { private static void Main(ssortingng[] args) { DeleteAllEntities(); CreateInitialEntities(); Owner o = LoadOwner(); Child c = LoadChild(); AssociateAndSave(o, c); } private static void AssociateAndSave(Owner o, Child c) { using (var context = new ModelEntities()) { // Exception occurs on the following line. o.Children.Add(c); context.Attach(o); context.SaveChanges(); } } private static Owner LoadOwner() { using (var context = new ModelEntities()) { return ((from o in context.Owners select o).First()); } } private static Child LoadChild() { using (var context = new ModelEntities()) { return ((from c in context.Children select c).First()); } } private static void CreateInitialEntities() { using (var context = new ModelEntities()) { Owner owner = new Owner(); Child child = new Child(); context.Owners.AddObject(owner); context.Children.AddObject(child); context.SaveChanges(); } } private static void DeleteAllEntities() { using (var context = new ModelEntities()) { List children = (from c in context.Children select c).ToList(); foreach (var c in children) context.Children.DeleteObject(c); List owners = (from o in context.Owners select o).ToList(); foreach (var o in owners) context.Owners.DeleteObject(o); context.SaveChanges(); } } } 

Vous devriez obtenir une référence aux objects enfant et propriétaire dans le même contexte. Une approche pour cela serait d’obtenir les identifiants puis de les transmettre en tant que parameters à la méthode AssociateAndSave(int oId, int cId) .

Ensuite, vous récupérez les références aux objects dans le même contexte et vous créez la pièce jointe.

 private static void Main(ssortingng[] args) { DeleteAllEntities(); CreateInitialEntities(); int oId = LoadOwnerId(); int cId = LoadChildId(); AssociateAndSave(oId, cId); } private static int LoadOwnerId() { using (var context = new ModelEntities()) { return (from o in context.Owners select o).First().Id; } } private static int LoadChildId() { using (var context = new ModelEntities()) { return (from c in context.Children select c).First().Id; } } private static void AssociateAndSave(int oId, int cId) { using (var context = new ModelEntities()) { var owner = (from o in context.Owners select o).FirstOrDefault(o => o.ID == oId); var child = (from o in context.Children select o).FirstOrDefault(c => c.ID == cId); owner.Children.Add(child); context.Attach(owner); context.SaveChanges(); } } 

Vous ne pouvez pas supprimer d’objects d’un contexte, avec une instance d’un autre contexte, car chaque contexte suit ses objects séparément.

Une idée serait de fournir à chacune de vos méthodes un paramètre de votre type de contexte afin que vos opérations soient effectuées dans le même contexte.

EX:

 private static void CrudOperationExample(DBContext contextInstane) { //perform crud operations. } 

Si vous voulez le faire plus gentiment, je vous suggère de rechercher une dependency injection, car elle est très utile dans les ORM.