Question

modifier n ° 2: la question a été résolue à mi-parcours. Regardez ci-dessous

En guise de question de suivi, est-ce que quelqu'un connaît un moyen non intrusif de résoudre ce que j'essaie de faire ci-dessous (à savoir, lier des objets les uns aux autres sans déclencher de boucles infinies)?

J'essaie de créer une application Web asp.net-mvc et d'obtenir une exception StackOverFlowException. Un contrôleur déclenche la commande suivante:

    public ActionResult ShowCountry(int id)
    {
        Country country = _gameService.GetCountry(id);
        return View(country);
    }

Le GameService le gère comme suit (WithCountryId est une extension):

    public Country GetCountry(int id)
    {
        return _gameRepository.GetCountries().WithCountryId(id).SingleOrDefault();
    }

Le GameRepository le gère comme suit:

    public IQueryable<Country> GetCountries()
    {
        var countries =  from c in _db.Countries
               select new Country
               {
                   Id = c.Id,
                   Name = c.Name,
                   ShortDescription = c.ShortDescription,
                   FlagImage = c.FlagImage,
                   Game = GetGames().Where(g => g.Id == c.GameId).SingleOrDefault(),
                   SubRegion = GetSubRegions().Where(sr => sr.Id == c.SubRegionId).SingleOrDefault(),
               };
        return countries;
    }

La méthode GetGames () provoque l'exception StackOverflowException:

    public IQueryable<Game> GetGames()
    {
        var games = from g in _db.Games                   
               select new Game
               {
                   Id = g.Id,
                   Name = g.Name

               };
        return games;

    }

Les objets My Business sont différents des classes linq2sql, c’est pourquoi je les remplis avec une nouvelle sélection.

Une exception non gérée du type 'System.StackOverflowException' s'est produite dans mscorlib.dll

modifier n ° 1: J'ai trouvé le coupable. Il utilise la méthode suivante. Il déclenche la méthode GetCountries () qui, à son tour, déclenche à nouveau GetSubRegions (), ad nauseam:

    public IQueryable<SubRegion> GetSubRegions()
    {
        return from sr in _db.SubRegions
               select new SubRegion
               {
                   Id = sr.Id,
                   Name = sr.Name,
                   ShortDescription = sr.ShortDescription,
                   Game = GetGames().Where(g => g.Id == sr.GameId).SingleOrDefault(),
                   Region = GetRegions().Where(r => r.Id == sr.RegionId).SingleOrDefault(),
                   Countries = new LazyList<Country>(GetCountries().Where(c => c.SubRegion.Id == sr.Id))
               };
    }

Il faudra peut-être penser à autre chose ici :) C'est ce qui se passe lorsque vous pensez dans un état d'esprit OO à cause de trop de café

Était-ce utile?

La solution

Le problème pourrait être le suivant: les pays ont des sous-régions et les sous-régions ont des pays. Je ne sais pas comment vous implémentez la liste paresseuse, mais cela pourrait continuer d'appeler GetCountries puis GetSubRegions et ainsi de suite. Pour le savoir, je lancerais le débogueur en définissant des points d'arrêt sur les en-têtes de méthodes GetCountries et GetSubRegions.

J'ai essayé des modèles similaires avec LinqToSql, mais il est difficile de faire fonctionner la navigation bidirectionnelle sans affecter trop les performances. C'est l'une des raisons pour lesquelles j'utilise NHibernate en ce moment.

Autres conseils

Hai! Je pense que vos modèles appellent une méthode de manière récursive sans le vouloir, ce qui entraîne un débordement de pile. Comme par exemple, votre objet Sous-région tente d'obtenir des objets Pays, lesquels doivent à leur tour recevoir des sous-régions.

Quoi qu'il en soit, il est toujours utile de vérifier la pile dans une exception StackOverflow. Si vous voyez une propriété être accédée à plusieurs reprises, c'est probablement parce que vous faites quelque chose comme ceci:

objet public MyProperty {set {MyProperty = value; }}

Il est plus facile de repérer des situations telles que la vôtre, où la méthode A appelle la méthode B, qui appelle la méthode A, car vous pouvez voir les mêmes méthodes s'afficher deux fois ou plus dans la pile d'appels.

Pour répondre à votre question modifiée, à savoir: "lier des objets les uns aux autres sans déclencher de boucles infinies":

En supposant que vous ayez une sorte de relation dans laquelle les deux parties doivent être informées de l'autre ... prenez contact avec toutes les entités concernées des deux côtés, puis associez-les ensemble, plutôt que d'essayer de récupérer le contenu d'un côté chercher automatiquement l'autre. Ou alors, faites simplement un chercher l’autre, puis corrigez le reste. Donc, dans votre cas, les options seraient:

Option 1:

  • Recherche tous les pays (les sous-régions sont laissées en blanc)
  • Extraire toutes les sous-régions (les pays sont vides)
  • Pour chaque sous-région, parcourez la liste des pays et ajoutez la sous-région au pays et le pays à la sous-région

Option 2:

  • Recherche tous les pays (les sous-régions sont laissées en blanc)
  • Extraire toutes les sous-régions, en définissant Sous-région.Pays via la liste de pays récupérée ci-dessus
  • Pour chaque sous-région, parcourez tous les pays et ajoutez-le à ce pays

(ou inversez le pays et la sous-région)

Ce sont essentiellement des réponses équialentes, cela change simplement lorsque vous faites des liens.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top