2

私はこれを一般的なブードゥー教のせいにするのではなく、理解しようとしています。

EF クエリを実行してデータを取得する.ToList()と、次のようになります。

IEnumerable<DatabaseMatch<CatName>> nameMatches = nameLogicMatcher.Match(myIQueryableOfCats).ToList();

一部の猫は複数の名前を持っているため、データベースに 2 回表示されますが、各猫には主な名前があります。したがって、これをフィルタリングするために、リスト内の猫のすべての ID を取得します。

List<int> catIds = nameMatches.Select(c => c.Match.CatId).ToList();

次に、すべての個別の ID を反復処理し、一致するすべての猫の名前を取得し、次のようにリストから主要な名前ではないものをすべて削除します。

foreach (int catId in catIds.Distinct())
{
    var allCatNameMatches = nameMatches.Where(c => c.Match.CatId == catId);

    var primaryMatch = allCatNameMatches.FirstOrDefault(c => c.Match.NameType == "Primary Name");

    nameMatches = nameMatches.Except(allCatNameMatches.Where(c => c != primaryMatch)); 
}

このコードは、最初に実行したときにハングしました。変だと思ったもの。私はそれを一歩踏み出しましたが、うまくいくように見えましたが、10回の反復の後(合計で100匹の猫に制限されています)、速度が低下し始め、最終的には氷河になり、完全にハングしました.

誤って集中的なデータベース作業を行っているのではないかと思いましたが、プロファイラーは、猫の名前の初期リストを取得する以外に実行された SQL を示していません。

IEnumerablenameMatches から aに変更し、最後の行Listに適切なものを配置することにしました。.ToList()これを行った後、すぐに完全に機能しました。

私が聞きたい質問は、なぜですか?

4

2 に答える 2

3

がなければ、遅延実行を待っている s のネストされたチェーンでToList()構築されます。チェーンを実行する各反復で呼び出していることを除けば、これはそれほど悪くないかもしれません。したがって、反復番号nでは、ループに含まれるフィルター操作をn-1回実行しています。1000 匹の異なる猫がいる場合、Linq チェーンは1000 + 99 + ... + 1回実行されます。(あなたはO(n³)である何かを持っていると思います!)nameMatchesIEnumerableFirstOrDefault

教訓は、遅延実行を使用する場合は、チェーンを 1 回だけ実行していることを確認することです。

于 2013-10-16T10:26:09.013 に答える
0

コードを少し単純化しましょう。

foreach (int catId in catIds.Distinct())
{
    var allCatNameMatches = nameMatches.Where(c => c.Match.CatId == catId);
    var primaryMatch = null;
    nameMatches = nameMatches.Except(allCatNameMatches.Where(c => c != primaryMatch)); 
}

そしてもう少し:

foreach (int catId in catIds.Distinct())
{
    nameMatches = nameMatches.Where(c => c.Match.CatId == catId);
    var primaryMatch = null;
    nameMatches = nameMatches.Except(nameMatches.Where(c => c != primaryMatch)); 
}

後者では、遅延実行により、 body の各パスがandforeachのチェーンを長くすることは明らかです。それから覚えておいてください。遅延実行されないため、各反復ですべてのチェーンを実行する必要があります。したがって、ハングします。WhereExceptvar primaryMatch = allCatNameMatches.FirstOrDefaultforeach

于 2013-10-16T10:25:05.030 に答える