web-dev-qa-db-ja.com

IQueryableとIEnumerableの違いは何ですか

私は違いに関して混乱しています。 .Netにはかなり新しいので、Linq拡張機能を使用してIEnumerablesをクエリできることを知っています。それで、このIQueryableとは何であり、どのように違いますか?


IQueryable [T]とIEnumerable [T]の違いは何ですか? この質問と重複しています。

145
James Hay

IEnumerable<T>は、Tの順方向専用カーソルを表します。 .NET 3.5は、LINQ standard query operatorsを含む述部または匿名関数を必要とする演算子とともに、WhereFirstなどのFunc<T>を含む拡張メソッドを追加しました。

IQueryable<T>は同じLINQ標準クエリ演算子を実装しますが、述語と匿名関数にExpression<Func<T>>を受け入れます。 Expression<T>はコンパイルされた式ツリーであり、クエリ可能プロバイダによって解析され、それに応じて使用できるメソッドの分割バージョン(必要に応じて「ハーフコンパイル済み」)です。

例えば:

IEnumerable<Person> people = GetEnumerablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();

IQueryable<Person> people = GetQueryablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();

最初のブロックでは、x => x.Age > 18は匿名メソッド(Func<Person, bool>)であり、他のメソッドと同様に実行できます。 Enumerable.Whereは、メソッドをyieldが返したtrueing値に対して、各人に対して1回メソッドを実行します.

2番目のブロックでは、x => x.Age > 18は式ツリー(Expression<Func<Person, bool>>)であり、「 'Age'プロパティ> 18」と考えることができます。

これにより、LINQ-to-SQLのようなものが存在できるようになります。これは、式ツリーを解析し、同等のSQLに変換できるためです。また、プロバイダーはIQueryableが列挙されるまで実行する必要がないため(結局、IEnumerable<T>を実装します)、複数のクエリ演算子を結合できます(上記の例ではWhereFirstOrDefault)(SQLでSELECT TOP 1を使用するなど)基になるデータソースに対してクエリ全体を実行する方法を賢く選択します。

見る:

183
Richard Szalay

実際には、LINQ-to-SQLのようなORMを使用している場合

  • IQueryableを作成すると、クエリはsqlに変換され、データベースサーバーで実行されます。
  • IEnumerableを作成すると、クエリを実行する前にすべての行がオブジェクトとしてメモリにプルされます。

どちらの場合でも、ToList()またはToArray()を呼び出さない場合、使用されるたびにクエリが実行されるため、たとえば、IQueryableがあり、4つのリストボックスを埋めます。それから、クエリはデータベースに対して4回実行されます。

また、クエリを拡張する場合:

q.Select(x.name = "a").ToList()

IQueryableを使用すると、生成されるSQLにはwhere name = "a"が含まれますが、IEnumerableを使用すると、データベースからさらに多くのロールがプルバックされ、x.name = "a"チェックが実行されます。 。ネット。

79
Ian Ringrose

「主な違いは、IQueryableに定義された拡張メソッドがFuncオブジェクトではなくExpressionオブジェクトを取ることです。つまり、受け取るデリゲートは呼び出すメソッドではなく式ツリーです。IEnumerableはインメモリコレクションでの作業に最適ですが、データベースやWebサービスなどのリモートデータソースの場合」

ソース: here

36
Gabe

IEnumerable IEnumerableは、メモリ内コレクションでの作業に最適です。 IEnumerableはアイテム間を移動せず、前方のみのコレクションです。

IQueryable IQueryableは、データベースやWebサービスなどのリモートデータソースに最適です。 IQueryableは、さまざまな興味深い遅延実行シナリオ(ページングやコンポジションベースのクエリなど)を可能にする非常に強力な機能です。

したがって、メモリ内コレクションを単純に反復処理する必要がある場合は、IEnumerableを使用します。Datasetやその他のデータソースなどのコレクションを操作する必要がある場合は、IQueryableを使用します

18
Talha

主な違いは、IEnumerableは常にすべての要素を列挙するのに対し、IQueryableはクエリに基づいて要素を列挙する、または他のことを行うことです。クエリは式(.Netコードのデータ表現)であり、結果を生成するためにIQueryProviderが探索/解釈/コンパイル/なんでもする必要があります。

クエリ式を持つことには2つの利点があります。

最初の利点は最適化です。 「Where」などの修飾子がクエリ式に含まれているため、IQueryProviderはそれ以外では不可能な最適化を適用できます。すべての要素を返し、「Where」句によってほとんどの要素を破棄する代わりに、プロバイダはハッシュテーブルを使用して、指定されたキーを持つアイテムを見つけることができます。

2番目の利点は柔軟性です。式は探索可能なデータ構造であるため、クエリをシリアル化し、リモートマシン(linq-to-sqlなど)に送信するなどのことができます。

9
Craig Gidney

まず、IEnumerableはSystem.Collections名前空間にあり、IQueryableはSystem.Linq名前空間にあります。リスト、配列コレクションなどのインメモリコレクションからデータをクエリするときにIEnumerableを使用し、アウトメモリ(リモートデータベース、サービスなど)コレクションからデータをクエリするときは、IQueryableを使用します。 IEnumerableはデータベースからデータをクエリするときに、サーバー側で選択クエリを実行し、クライアント側でメモリ内のデータをロードしてからデータをフィルター処理するためです。したがって、より多くの作業を行い、遅くなります。データベースからデータをクエリしている間、IQueryableはすべてのフィルターを使用してサーバー側で選択クエリを実行します。したがって、作業が少なくなり、高速になります。

1
Nayeem Mansoori

IQueriableはIEnumerableと同じですが、Linqでカスタムクエリを実装するための追加機能も提供します。 MSDNの説明は次のとおりです。 http://msdn.Microsoft.com/en-us/library/system.linq.iqueryable.aspx

1
Andrew Bezzub