3

編集#2:質問は途中で解決しました。下を見てください

フォローアップの質問として、私が以下でやろうとしていることを解決するための邪魔にならない方法を知っている人はいますか (つまり、無限ループをトリガーせずにオブジェクトを相互にリンクします)?


asp.net-mvc Web アプリケーションを作成しようとすると、StackOverFlowException が発生します。コントローラーは次のコマンドをトリガーします。

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

GameService は次のように処理します (WithCountryId は拡張機能です)。

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

GameRepository は次のように処理します。

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

GetGames() メソッドにより、StackOverflowException が発生します。

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

               };
        return games;

    }

私のビジネス オブジェクトは linq2sql クラスとは異なります。そのため、それらに select new を入力します。

タイプ 'System.StackOverflowException' の未処理の例外が mscorlib.dll で発生しました


編集#1:犯人を見つけました。それは次のメソッドです。GetCountries()メソッドをトリガーし、その代わりにGetSubRegions()を再びトリガーします。

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

ここで何か他のことを考えなければならないかもしれません:)コーヒーが多すぎるためにオブジェクト指向の考え方で考えると、それが起こります

4

3 に答える 3

3

ハイ!あなたのモデルは意図せずにメソッドを再帰的に呼び出していると思います。その結果、スタック オーバーフローが発生します。たとえば、Subregion オブジェクトが Country オブジェクトを取得しようとしているのと同様に、Country オブジェクトは Subregions を取得する必要があります。

とにかく、StackOverflow 例外でスタックをチェックすることは常に役立ちます。プロパティが何度もアクセスされている場合は、次のようなことをしている可能性が最も高いです。

パブリック オブジェクト MyProperty { セット { MyProperty = 値; }}

メソッド A がメソッド A を呼び出すメソッド B を呼び出しているような状況を簡単に見つけることができます。コール スタックに同じメソッドが 2 回以上表示されていることがわかるからです。

于 2008-10-26T19:45:02.150 に答える
1

問題はこれかもしれません: 国にはサブリージョンがあり、サブリージョンには国があります。遅延リストをどのように実装するかはわかりませんが、GetCountries、GetSubRegions などを呼び出し続ける可能性があります。それを見つけるには、GetCountries および GetSubRegions メソッド ヘッダーにブレークポイントを設定してデバッガーを起動します。

LinqToSql で同様のパターンを試してみましたが、パフォーマンスに大きな影響を与えずに双方向ナビゲーションを機能させることは困難です。それが、私が現在 NHibernate を使用している理由の 1 つです。

于 2008-10-26T19:53:27.733 に答える
1

編集した質問、つまり「無限ループをトリガーせずにオブジェクトを相互にリンクする」に答えるには:

両側が他方について知る必要があるある種の関係があると仮定すると...片側のフェッチを自動的に取得しようとするのではなく、両側のすべての関連エンティティを取得し、それらをリンクします他の。または、一方を他方にフェッチさせてから、残りを修正します。したがって、あなたの場合、オプションは次のようになります。

オプション1:

  • すべての国を取得します (サブリージョンを空白のままにします)
  • すべてのサブリージョンを取得します (国は空白のままにします)
  • サブリージョンごとに、国のリストに目を通し、サブリージョンを国に追加し、国をサブリージョンに追加します

オプション 2:

  • すべての国を取得します (サブリージョンを空白のままにします)
  • 上記で取得した国のリストを介して Subregion.Countries を設定し、すべてのサブリージョンを取得します
  • サブリージョンごとに、そのすべての国を調べて、その国に追加します

(または逆の国と小地域)

それらは基本的に同等の答えであり、リンクを行うと変化するだけです。

于 2008-10-26T19:54:00.633 に答える