web-dev-qa-db-ja.com

IQueryable linqクエリをIEnumerable <T>に変換すると、動作するlinqに最適化された方法がキャンセルされますか?

私は.NETの初心者ですが、多くのlinqクエリを次々に適用できるため、linqがどのように機能するのか疑問に思っていましたが、情報の転送またはリストへの変換に使用されるまで、実際には実行されません。等.
linqクエリを取得するには、Sqlにwhereフィルターを直接適用するIQueryable<T>を使用して2つの重要な方法があり、IEnumerableはすべてのレコードを取得してメモリ上で機能します。ただし、このコードを見てみましょう。

            //Linq dynamic library
            IQueryable<Table> myResult = db.Categories
                .Where(a => a.Name.Contains(StringName))
                .OrderBy("Name")
                .Skip(0)
                .Take(10);

            if (myResult != null)
            {
                return myResult.AsEnumerable();
            } 
            else
            { return null; }

私はLinqダイナミックライブラリを使用していますが、このクエリからの直接の結果はIQueryable<T>で取得されています。クエリが最終的にIEnumerableとして返される場合、クエリは本当にsqlでフィルターされていますか?またはそれはメモリにありますか?

20
Arturo Suarez

引き続きデータベースで実行されますので、心配しないでください。基本的には、Whereなどの実装が使用されるかどうかにかかっています。 _IQueryable<T>_のメソッドを呼び出している間-Queryable拡張メソッドを介して-式ツリーを使用します。そのクエリからfetchを開始すると、SQLに変換されてデータベースに送信されます。

一方、これらのメソッドのいずれかを使用する場合afterは、それを_IEnumerable<T>_(コンパイル時の型に関して)として取得し、以下の拡張メソッドを使用します。 Enumerable、および残りのすべての処理wouldはインプロセスで行われます。

例として、これを考慮してください:

_var query = db.People
              .Where(x => x.Name.StartsWith("J"))
              .AsEnumerable()
              .Where(x => x.Age > 20);
_

ここでAsEnumerable()justは入力シーケンスを返しますが、_IEnumerable<T>_として入力されます。この場合、データベースクエリは、名前がJで始まる人のみを返し、代わりに年齢フィルタリングがクライアントで行われます。

34
Jon Skeet

IEnumerable<T>を返し、クエリをさらに絞り込むと、メモリ内でさらに絞り込みが行われます。 IQueryable<T>で表現された部分は、適切なSQLステートメントに変換されます(LINQ-to-SQLの場合は明らかに)。

より長く、より詳細な回答については IEnumerable <T>とIQueryable <T>を返す を参照してください。

5
driis