4
            var costCenters = from c in dbContext.CostCenters //no sql call here
                          orderby c.DisplayRank descending
                          select c;


            List<CostCenter> lstCostCenter = costCenters.ToList();//Immediate execution to sql the first time

            lstCostCenter = costCenters.ToList();//no Sql call ??

            int test = costCenters.Count();//Call Sql everytime
            test = costCenters.Count();//Call Sql again???

Entity Framework 5 を使用しています

私はLinqを学び始めています。どの即時実行関数が毎回 SQL を呼び出すかについて、私は本当に混乱しています。上記のサンプルでわかるように、ToList() と Count() はどちらも即時実行関数ですが、Count() のみがサブシーケンス呼び出しで sql に接続します。ToList() は SQL に 1 回接続しますが、Count() は毎回 SQL に接続します。
どの linq 関数が sql を複数回呼び出さないかを特定するにはどうすればよいですか?

4

3 に答える 3

4

まず第一に、ToList()は遅延実行を使用しません。それは常に情報をすぐに実現します。すでにすべてのエンティティを取得しているため、毎回データベースに戻るわけではありません。

どの演算子が何をするかを知るには、このリンクを見てください。

于 2013-01-09T15:31:04.427 に答える
3

違いは、ToList()を初めて呼び出すときに、IQueryable(クエリの単なる定義)をIEnumerable(データベースのクエリ)のリストに変換することです。つまり、現在メモリ内にあるオブジェクトのリストが返されるため、結果のリストでそれ以降のLINQ呼び出しでは、メモリ内オブジェクトで機能するIEnumerableバージョンが使用されます。さらに、EFには結果をキャッシュする機能があるため、元のIQueryable参照でToListを呼び出した場合でも、データベースからオブジェクトをフェッチする代わりに、メモリ内オブジェクトを使用する可能性があります。推測しているcountのクエリはToListのクエリと同じではないため(これは集約/グループ化の一種です)、Countのクエリはキャッシュされた結果をカウントするのではなく、データベースに再度ヒットします。また、DBエンジンがカウントを提供するのにより効率的です。

あなたの例でcostCentersは、はIQueryableです。これは、クエリを定義するだけで、まだToListを呼び出さないためです。 lstCostCenterToListで実行された後のクエリからのメモリ内の結果を表すIEnumerableです。通常、IQueryableで実行されたときに結果、.Count、.ToListなどを生成する即時呼び出しは、DB呼び出し(再利用可能なキャッシュされた結果が見つかった場合を除く)、およびIEnumerableオブジェクト(この場合は)を呼び出します。lstCostCenter)メモリ内で動作します。

より予測可能な結果を​​得るには、最初にIQueryableでToListを呼び出し、それ以降はIEnumerableですべての呼び出しを行います。言い換えれば、あなたが呼び出すものはすべてlstCostCenterデータベースにヒットしないことが保証されています。結果のリストが大きくなることが予想される場合を除いて、これは通常、それを処理するための最良の方法です。lstCostCenter.Where(x=>x.Blah > 5)たとえば、lstCostCenterで10,000個のオブジェクトが作成された場合、メモリ内の10,000個のオブジェクトすべてをループしてフィルタリングするため、おそらく実行したくないでしょう。このような場合、最初にIQueryableに追加の呼び出しを追加してから、ToListを呼び出してクエリを変更し、大きなセットの処理に優れたDBエンジンを活用することをお勧めしますcostCenters.Where(x=>x.Blah > 5).ToList()

于 2013-01-09T16:03:49.307 に答える
1

http://msdn.microsoft.com/en-us/library/bb738633.aspx

違いは「強制執行」にあります。クエリの即時実行を強制すると、結果がキャッシュされます。また、ToList()、ToArray() などの変換演算子、さらに foreach は強制実行として分類されるため、それ以降の呼び出しはメモリ内キャッシュでのみ動作します。Count()、First()、Max()、および Average() は強制実行とは見なされません...これらはクエリの一部です...推測します。

于 2013-01-09T16:31:22.583 に答える