ADO.Net Entity Framework Un object quadro non può essere referenziato da più istanze di IEntityChangeTracker

Sto cercando di salvare il mio contatto, che ha riferimenti a ContactRelation (solo il rapporto del contatto, sposato, single, ecc.) E Paese. Ma ogni volta che provo a salvare il mio contatto, che viene convalidato, ottengo l’eccezione “ADO.Net Entity Framework Un object entity framework non può essere referenziato da più istanze di IEntityChangeTracker”

public Contact CreateContact(Contact contact) { _entities.AddToContact(contact); //throws the exception _entities.SaveChanges(); return contact ; } 

Sto usando un design MVC liberamente accoppiato con servizi e repository. Ho letto molti post su questa eccezione ma nessuno mi dà una risposta funzionante …

Grazie, Peter

[Aggiornare]
Poiché viene utilizzato L2E, è necessario prima salvare tutti gli oggetti collegati prima di poter salvare l’object principale. Il che ha senso altrimenti si creerebbe (nel mio esempio) un artista senza il suo object di contatto. Questo non è consentito dal design del database.
[/Aggiornare]

Ecco la mia implementazione che ha funzionato.

 [AcceptVerbs(HttpVerbs.Post)] public ActionResult Create([Bind(Exclude = "Id")] Artist artist, [Bind(Prefix = "Contact")] Contact contact, [Bind(Prefix = "Country")] Country country, [Bind(Prefix = "ContactRelationship")] ContactRelationship contactRelationship) { ViewData["Countries"] = new SelectList(new CountryService(_msw).ListCountries().OrderBy(c => c.Name), "ID", "Name"); ViewData["ContactRelationships"] = new SelectList(new ContactRelationshipService(_msw).ListContactRelationships().OrderBy(c => c.ID), "ID", "Description"); country = _countryService.GetCountryById(country.ID); contact.Country = country; contactRelationship = _contactRelationshipService.GetContactRelationship(contactRelationship.ID); contact.ContactRelationship = contactRelationship; if(_contactService.CreateContact(contact)){ artist.Contact = contact; if (_service.CreateArtist(artist)) return RedirectToAction("Index"); } return View("Create"); } 

E poi nel mio ContactRepository:

 public Contact CreateContact(Contact contact) { _entities.AddToContact(contact); //no longer throws the exception _entities.SaveChanges(); return contact ; } 

Ho anche trovato su questo sito Web che è meglio mantenere lo stesso contesto in tutta l’applicazione, quindi ora sto usando una class Data speciale per questo:

Rick Strahl e Samuel Maecham mi hanno insegnato che dovresti mantenere il tuo data-base per utente per richiesta. Il che significa metterlo in HttpContext per le applicazioni web. Leggi tutto su questo qui

 public class Data { public static MyDBEntities MyDBEntities { get { if (HttpContext.Current != null && HttpContext.Current["myDBEntities"] == null) { HttpContext.Current["myDBEntities"] = new MyDBEntities (); } return HttpContext.Current["myDBEntities"] as MyDBEntities; } set { if(HttpContext.Current != null) HttpContext.Current["myDBEntities"] = value; } } } 

Ho visto questo prima, potrebbe essere necessario convertire il campo di riferimento in un EntityKey prima di salvare e poi caricarlo dopo il suo salvataggio. Prova questo codice invece:

 public Contact CreateContact(Contact contact){ contact.ConvertContactRelationToReference(); _entities.AddToContact(contact); //throws the exception _entities.SaveChanges(); contact.ContactRelation.Load(); return contact; } public partial class Contact { public void ConvertContactRelationToReference() { var crId = ContactRelation.Id; ContactRelation = null; ContactRelationReference.EntityKey = new EntityKey("MyEntities.ContactRelations", "Id", crId); } } 

Naturalmente, potrebbe essere necessario modificare parte di questo codice in base alla struttura esatta del database.

Ummm mi chiedo se qualcuno può per favore sanità controllare la mia soluzione. È molto simile alla risposta accettata sotto, ma dopo aver letto il blog di Rick Strahl su DataContext Life Management temo che questa non sia una soluzione thread-safe per un’applicazione web.

Ho anche capito l’istanza in cui stavo ricevendo questo messaggio di errore accedendo al mio contesto object usando il modello singleton.

Ho aggiunto quanto segue alla class MyObjectContext:

 // singleton private static MyObjectContext context; public static MyObjectContext getInstance() { if (context == null) { context = new MyObjectContext (); } return context; } 

E nel mio mappatore di repository per quadro invece di istanziare una nuova istanza di MyObjectContext che uso

 var db = MyObjectContext.getInstance(); 

Sono stupido qui? Sembra funzionare.