ADO.Net Entity Framework Un objet entité ne peut pas être référencé par plusieurs instances de IEntityChangeTracker

ado.net c# entity-framework

Question

J'essaye de sauvegarder mon contact, qui a des références à ContactRelation (juste la relation du contact, marié, célibataire, etc.) et au pays. Mais chaque fois que j'essaye de sauvegarder mon contact, ce qui est validé, je reçois l'exception "ADO.Net Entity Framework Un objet d'entité ne peut pas être référencé par plusieurs instances de IEntityChangeTracker"

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

J'utilise une conception MVC faiblement couplée avec des services et des référentiels. J'ai lu beaucoup d'articles sur cette exception, mais aucun ne m'a donné de réponse valable ...

Merci Peter

Réponse acceptée

[Mettre à jour]
Étant donné que L2E est utilisé, vous devez d'abord enregistrer tous les objets liés avant de pouvoir enregistrer l'objet principal. Ce qui est logique sinon vous créeriez (dans mon exemple) un artiste sans son objet de contact. Ce n'est pas autorisé par la conception de la base de données.
[/Mettre à jour]

Voici mon implémentation qui a fonctionné.

[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");
}

Et puis dans mon ContactRepository:

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

J'ai également constaté sur ce site Web qu'il était préférable de conserver le même contexte dans toute l'application; j'utilise donc une classe de données spéciale pour cela:

Rick Strahl et Samuel Maecham m'ont appris que vous devriez conserver votre contexte de données par utilisateur et par demande. Ce qui signifie le placer dans HttpContext pour les applications Web. Lire tout à ce sujet ici

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

Réponse populaire

Je l'ai déjà vu, vous devrez peut-être convertir le champ Référence en EntityKey avant de l'enregistrer, puis le charger après son enregistrement. Essayez plutôt ce code:

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

Bien sûr, une partie de ce code devra peut-être être modifiée en fonction de la structure exacte de votre base de données.



Related

Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow