Domanda

modifica n. 2: Domanda risolta a metà. Guarda in basso

Come domanda di follow-up, qualcuno conosce un modo non intrusivo per risolvere ciò che sto cercando di fare di seguito (vale a dire, collegare gli oggetti tra loro senza innescare loop infiniti)?


Provo a creare un'applicazione web asp.net-mvc e ottengo StackOverFlowException. Un controller attiva il seguente comando:

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

GameService lo gestisce in questo modo (WithCountryId è un'estensione):

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

GameRepository lo gestisce in questo modo:

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

Il metodo GetGames () causa StackOverflowException:

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

               };
        return games;

    }

Gli oggetti My Business sono diversi dalle classi linq2sql, ecco perché li riempio con una nuova selezione.

Si è verificata un'eccezione non gestita del tipo "System.StackOverflowException" in mscorlib.dll


modifica n. 1: ho trovato il colpevole, è il seguente metodo, innesca il metodo GetCountries () che a sua volta innesca 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))
               };
    }

Potrebbe essere necessario pensare a qualcos'altro qui :) Ecco cosa succede quando si pensa in una mentalità OO a causa del troppo caffè

È stato utile?

Soluzione

Il problema potrebbe essere questo: i paesi hanno sottoregioni e le sottoregioni hanno paesi. Non so come si implementa l'elenco pigro, ma ciò potrebbe continuare a chiamare GetCountries e quindi GetSubRegions e così via. Per scoprirlo, vorrei avviare il debugger e impostare i punti di interruzione nelle intestazioni del metodo GetCountries e GetSubRegions.

Ho provato modelli simili con LinqToSql, ma è difficile far funzionare la navigazione bidirezionale senza influire troppo sulle prestazioni. Questo è uno dei motivi per cui sto usando NHibernate in questo momento.

Altri suggerimenti

Hai! Penso che i tuoi modelli chiamino ricorsivamente un metodo involontariamente, il che si traduce in un overflow dello stack. Ad esempio, l'oggetto Sottoregione sta cercando di ottenere oggetti Paese, che a loro volta devono ottenere Sottoregioni.

In ogni caso, aiuta sempre a controllare lo stack in un'eccezione StackOverflow. Se vedi l'accesso a una proprietà più e più volte, è molto probabile perché stai facendo qualcosa del genere:

oggetto pubblico MyProperty {set {MyProperty = value; }}

È più facile individuare situazioni come la tua, in cui il metodo A chiama il metodo B che chiama il metodo A, perché puoi vedere gli stessi metodi mostrati due o più volte nello stack di chiamate.

Per rispondere alla tua domanda modificata, vale a dire: " collegare tra loro oggetti senza innescare loop infiniti " ;:

Supponendo che tu abbia una sorta di relazione in cui entrambe le parti devono sapere dell'altra ... prendi possesso di tutte le entità rilevanti in entrambe le parti, quindi collegale insieme, piuttosto che cercare di recuperare un lato recupera automaticamente l'altro. Oppure fai semplicemente uno recuperare l'altro lato, quindi aggiusta quello rimanente. Quindi nel tuo caso, le opzioni sarebbero:

Opzione 1:

  • Scarica tutti i paesi (lasciando vuote le sottoregioni)
  • Scarica tutte le sottoregioni (lasciando vuoti i Paesi)
  • Per ogni Sottoregione, guardare l'elenco dei Paesi e aggiungere la Sottoregione al Paese e il Paese alla Sottoregione

Opzione 2:

  • Scarica tutti i paesi (lasciando vuote le sottoregioni)
  • Recupera tutte le sottoregioni, impostando Sottoregione. Paesi tramite l'elenco dei paesi recuperato sopra
  • Per ogni sottoregione, esaminare tutti i suoi paesi e aggiungerlo a quel paese

(O paese inverso e sottoregione)

Sono sostanzialmente risposte equivalenti, cambia solo quando esegui alcuni dei collegamenti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top