Pergunta

edição # 2: Pergunta resolvido halfways. Olhada abaixo

Como uma questão de acompanhamento, alguém sabe de uma forma não-intrusiva para resolver o que eu estou tentando fazer a seguir (ou seja, ligando objetos uns aos outros sem disparar loops infinitos)?


Eu tento criar um aplicativo web asp.net-mvc, e obter uma StackOverflowException. Um controlador aciona o seguinte comando:

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

As alças GameService-lo assim (WithCountryId é uma extensão):

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

As alças GameRepository assim:

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

Os GetGames () faz com que o método StackOverflowException:

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

               };
        return games;

    }

objetos Meu negócio são diferentes das classes Linq2Sql, é por isso que eu enchê-los com um seleto nova.

Uma exceção sem tratamento do tipo 'System.StackOverflowException' em mscorlib.dll


edição # 1: eu encontrei o culpado, é o método seguinte, ele aciona os GetCountries () método, que em troca aciona os GetSubRegions () novamente, 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))
               };
    }

Poderá ter de pensar em outra coisa aqui :) É isso que acontece quando você pensa em uma mentalidade OO por causa do excesso de café

Foi útil?

Solução

O problema pode ser este: países têm sub-regiões e sub-regiões têm países. Eu não sei como você implementar a lista de preguiçoso, mas que poderia continuar chamando GetCountries e GetSubRegions seguida, e assim por diante. Para descobrir isso, eu iria lançar o depurador en pontos de interrupção definido no cabeçalhos método getCountries e GetSubRegions.

Eu tentei padrões semelhantes com LinqToSql, mas é difícil fazer o trabalho de navegação bidirecional sem afetar o desempenho muito. Essa é uma das razões que eu estou usando NHibernate agora.

Outras dicas

Hai! Acho que seus modelos são recursivamente chamar um método sem querer, o que resulta no estouro de pilha. Como, por exemplo, o seu objeto Sub-região está a tentar obter objetos país, que por sua vez têm de obter sub-regiões.

De qualquer forma, ele sempre ajuda a verificar a pilha em uma exceção StackOverflow. Se você ver uma propriedade que está sendo acessado mais e mais, o seu mais provável, porque você está fazendo algo parecido com isto:

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

É mais fácil de detectar situações como a sua, onde o método A chama o método B, que chama o método A, porque você pode ver os mesmos métodos aparecer duas ou mais vezes na pilha de chamadas.

Para responder à sua pergunta editada, a saber: "vinculando os objetos uns aos outros sem disparar loops infinitos":

Assumindo que você tem algum tipo de relação em que ambos os lados precisam de saber sobre o outro ... se apossar de todas as entidades relevantes em ambos os lados, em seguida, ligá-los juntos, em vez de tentar fazer a busca de um lado buscar automaticamente o outro. Ou apenas fazer um lado buscar o outro, e então arrumar o restante. Assim, no seu caso, as opções seriam:

Opção 1:

  • Obter todos os países (deixando Sub-regiões em branco)
  • Obter todos os Sub-regiões (deixando os países em branco)
  • Para cada sub-região, olhar através da lista dos países e adicionar a sub-região do País e do País para a Sub-Região

Opção 2:

  • Obter todos os países (deixando Sub-regiões em branco)
  • Obter todas as sub-regiões, definindo Subregion.Countries através da lista de países buscado acima
  • Para cada sub-região, passar por todos os países e adicioná-la a esse país

(ou país reversa e sub-região)

Eles são respostas basicamente equialent, ela apenas muda quando você faz parte da ligação.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top