IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Framework .NET Discussion :

Erreur multiple instances of IEntityChangeTracker


Sujet :

Framework .NET

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 14
    Points : 13
    Points
    13
    Par défaut Erreur multiple instances of IEntityChangeTracker
    Bonjour à tous,

    Je développe en ce moment une application web avec .NET MVC 2.

    J’ai deux entités : group et news. Une news est visible par un ou plusieurs groups. J’utilise un repository différent pour les deux.

    Dans mon contrôleur pour news, la fonction « create » récupère les informations envoyées par le formulaire de cette façon :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
            //
            // GET: /NewsAdmin/Create/
            [HttpGet]
            public ActionResult Create()
            {
                return View(new CreateNewsViewModel(new News()));
            }
            //
            // POST: /NewsAdmin/Create/
            [HttpPost]
            public ActionResult Create(CreateNewsViewModel model)
            {
                model.news.CategoryId = Int32.Parse(Request.Form["news.CategoryId"]);
     
                if (ModelState.IsValid)
                {
     
                    News news = new News();
     
                    DateTime date = DateTime.Now;
     
                    //AuthorId a recuperer
                    news.AuthorId = 1;
     
                    news.Title = IntranetTools.UppercaseFirst(model.news.Title.Trim());
                    news.Content = model.news.Content;
                    news.IsVisible = Request.Form["news.IsVisible"].Contains("true");
                    news.CreateDate = date;
                    news.PublicationDate = date;
                    news.LastChangedDate = date;
                    news.CategoryId = model.news.CategoryId;
     
                    // Collection des groupes concernés
                    foreach (var c in model.allGroups)
                    {
                        if (Request.Form["" + c.GroupId].Contains("true"))
                        {
                            News.Groups.Add(c);
                        }
                    }
     
                    _newsRepository.AddToNewsSet(news);
                    _newsRepository.SaveChanges();
     
                    return Redirect("/NewsAdmin/Index/");
                }
                return View(model);
            }

    Je pars du principe que mes groups sont déjà créés. Je ne fais qu’insérer les groups choisis par l’utilisateur via des checkbox. Dans mon « CreateNewsViewModel », je crée une liste de groups qui contient tous les groups existant dans ma bdd. Je récupère la liste dans ma vue, par le biais d’un « for each » je crée des checkbox pour chacun des groups. Je réutilise la même liste dans mon contrôleur pour comparer si les checkbox ont été cochées. Pour chaque occurrence à true, j’ajoute les groups dans la collection de groups de ma news nouvellement créée.

    Et là, c’est le drame.

    J’obtiens l’erreur :
    An entity object cannot be referenced by multiple instances of IEntityChangeTracker.
    J'ai fais des recherches sur cette erreur, mais je ne trouve pas une réponse qui corresponde exactement à mon problème.

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    C'est quoi l'ORM utilisé ? Linq to SQL ? Entity Framework ?

    A priori les groupes ont été chargés avec un DataContext (ou ObjectContext si c'est EF) différent de celui que tu utilises pour insérer les données. Une entité ne peut pas être manipulée par deux contexts différents. Donc il faut que tu utilises le même context pour charger les groupes et insérer les news.

    Le plus simple, c'est de recharger les groupes plutôt que d'utiliser ceux qui sont dans ton CreateNewsViewModel :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
                    foreach (var c in _newsRepository.Groups)
                    {
                        if (Request.Form["" + c.GroupId].Contains("true"))
                        {
                            News.Groups.Add(c);
                        }
                    }

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 14
    Points : 13
    Points
    13
    Par défaut
    J'utilise Entity Framework.

    J'ai testé en chargeant dans une liste mes groups dans mon contrôleur au lieu de prendre celui de mon viewmodel :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
                   List<Group> groups = new List<Group>();
                    groups = _groupsRepository.getAllGroups().ToList();
     
                    // Collection des groupes concernés
                    foreach (var c in groups)
                    {
                        if (Request.Form["" + c.GroupId].Contains("true"))
                        {
                            news.Groups.Add(c);
                        }
                    }
    Malheureusement je retrouve toujours cette erreur :

    An entity object cannot be referenced by multiple instances of IEntityChangeTracker.

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    Ah ok... ton _newsRepository et ton _groupRepository utilisent des ObjectContexts différents alors ? Cherche pas plus loin, le problème vient de là... Il faut absolument utiliser le même.

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 14
    Points : 13
    Points
    13
    Par défaut
    Dans l'idéal j'aimerais garder plusieurs repository, car j'ai beaucoup d'entités et je me retrouverai certainement dans la même situation pour d'autres collections. Cependant j'ai trouvé une piste de solution :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
                    ObjectContext context  = _newsRepository.Context;
                    ObjectContext context2 = _groupsRepository.Context;
     
                    // Collection des groupes concernés
                    foreach (var c in groups)
                    {
                        if (Request.Form["" + c.GroupId].Contains("true"))
                        {
                            context2.Detach(c);
                            context.Attach(c);
                            news.Groups.Add(c);
                        }
                    }
    J'ai créé un getter pour récupérer le context de mes repository. Je détache donc chaque group que je veux insérer du context créé dans _groupsRepository pour l'attacher au context de _newsRepository.

    La solution finale serait donc de créer un context unique par session utilisateur que j'enverrai en paramètre lorsque j'appelle un repository.

    J'utilise Ninject pour la DI.

    Pensez-vous que je peux trouver une solution convenable dans ce sens ?

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    Citation Envoyé par mouchiche123 Voir le message
    J'ai créé un getter pour récupérer le context de mes repository. Je détache donc chaque group que je veux insérer du context créé dans _groupsRepository pour l'attacher au context de _newsRepository.
    Ca me semble une solution viable, mais pas idéale

    Citation Envoyé par mouchiche123 Voir le message
    La solution finale serait donc de créer un context unique par session utilisateur que j'enverrai en paramètre lorsque j'appelle un repository.
    C'est sans doute la meilleure option, à un petit détail près : il vaudrait mieux créer un context par requête plutôt que par session. Tu peux potentiellement avoir un très grand nombre de sessions actives à un moment donné, donc si tu gardes la connexion DB ouverte pendant toute la durée de la session, tu vas saturer la DB. Avec une connexion par requête, tu limites la durée de la connexion et tu libères donc des ressources pour les autres requêtes.

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 14
    Points : 13
    Points
    13
    Par défaut
    Effectivement, ce serait mieux. Seulement, comment je pourrais appliquer cette solution ? Car je ne sais pas comment créer un context pour une requête.

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    Tu pourrais créer le context au début de la requête (évènement BeginRequest de l'application), le conserver dans le HttpContext (HttpContext.Current.Items), et le fermer à la fin de la requête (évènement EndRequest).

    Je sais pas si c'est la meilleure solution, je suis pas expert en ASP.NET... il y a peut-être plus simple

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 14
    Points : 13
    Points
    13
    Par défaut
    Merci beaucoup pour ton aide. Je vais essayer cette méthode.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 1
    Dernier message: 17/08/2009, 23h17
  2. Réponses: 8
    Dernier message: 19/09/2006, 16h42
  3. [C++] DLL Multiples instances
    Par ouquoi dans le forum C++
    Réponses: 2
    Dernier message: 18/07/2006, 17h25
  4. [VBA-E]Gestion d'erreurs multiple
    Par icetechnik dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 18/04/2006, 23h35
  5. [MySQL] Erreurs multiples de type Undefined index
    Par alleramiens dans le forum PHP & Base de données
    Réponses: 17
    Dernier message: 27/01/2006, 21h39

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo