Pregunta

editar # 2: pregunta resuelta a medias. Mira abajo

Como una pregunta de seguimiento, ¿alguien sabe de una manera no intrusiva de resolver lo que estoy tratando de hacer a continuación (es decir, vincular objetos entre sí sin desencadenar bucles infinitos)?


Intento crear una aplicación web asp.net-mvc y obtengo una excepción StackOverFlowException. Un controlador activa el siguiente comando:

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

El GameService lo maneja así (WithCountryId es una extensión):

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

El GameRepository lo maneja así:

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

El método GetGames () causa la excepción StackOverflowException:

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

               };
        return games;

    }

Los objetos de Mi negocio son diferentes de las clases de linq2sql, por eso los lleno con una selección nueva.

Se produjo una excepción no controlada del tipo 'System.StackOverflowException' en mscorlib.dll


editar # 1: he encontrado al culpable, es el siguiente método, activa el método GetCountries () que, a cambio, activa GetSubRegions () nuevamente, naufragio:

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

Puede que tenga que pensar en otra cosa aquí :) Eso es lo que sucede cuando piensa en una mentalidad de OO debido a un exceso de café

¿Fue útil?

Solución

El problema podría ser este: los países tienen subregiones y las subregiones tienen países. No sé cómo implementa la lista lenta, pero eso podría seguir llamando a GetCountries y luego a GetSubRegions y así sucesivamente. Para averiguarlo, lanzaría los puntos de interrupción del conjunto de depuración en los encabezados de los métodos GetCountries y GetSubRegions.

Probé patrones similares con LinqToSql, pero es difícil hacer que la navegación bidireccional funcione sin afectar mucho el rendimiento. Esa es una de las razones por las que estoy usando NHibernate en este momento.

Otros consejos

¡Hai! Creo que sus modelos están recurriendo involuntariamente a un método, lo que provoca el desbordamiento de la pila. Como, por ejemplo, su objeto Subregión está tratando de obtener objetos País, que a su vez tienen que obtener Subregiones.

De todos modos, siempre es útil verificar la pila en una excepción StackOverflow. Si ve que se accede a una propiedad una y otra vez, es muy probable que esté haciendo algo como esto:

objeto público MyProperty {set {MyProperty = valor; }}

Es más fácil detectar situaciones como la tuya, donde el método A llama al método B que llama al método A, porque puedes ver los mismos métodos que aparecen dos o más veces en la pila de llamadas.

Para responder a su pregunta editada, es decir: " vincular objetos entre sí sin desencadenar bucles infinitos " ;:

Suponiendo que tienes algún tipo de relación en la que ambas partes necesitan saber sobre la otra ... hazte con todas las entidades relevantes en ambas partes, luego vincúlalas, en lugar de tratar de hacer una búsqueda de un lado automáticamente buscar el otro. O simplemente haga que un lado recoja el otro, y luego arregle el restante. Así que en tu caso, las opciones serían:

Opción 1:

  • Recuperar todos los países (dejando en blanco las subregiones)
  • Recupere todas las subregiones (dejando los países en blanco)
  • Para cada Subregión, revise la lista de Países y agregue la Subregión al País y el País a la Subregión

Opción 2:

  • Recuperar todos los países (dejando en blanco las subregiones)
  • Obtenga todas las subregiones, configurando la subregión. Países a través de la lista de países que se encuentra arriba
  • Para cada subregión, recorra todos los países y añádalo a ese país

(O país y subregión inversos)

Son básicamente respuestas iguales, solo cambian cuando haces algunos de los enlaces.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top