IQueryable<T>とはどう違いIEnumerable<T>ますか?
この質問と重複するIQueryable と IEnumerable の違いは何ですかも参照してください。
まず第一に、インターフェースを拡張するので、「プレーン」でできることは何でも、.IQueryable<T> IEnumerable<T>IEnumerable<T>IQueryable<T>
IEnumerable<T>GetEnumerator()を返すメソッドがあり、そのメソッドをEnumerator<T>呼び出してTMoveNext()のシーケンスを反復処理できます。
1 つはIQueryable<T>クエリプロバイダー(LINQ to SQL プロバイダーなど) を指し、もう 1 つIEnumerable<T> はオブジェクトを実行時にトラバース可能な抽象構文ツリーとして表すクエリ式を指します。指定されたクエリ プロバイダーによって理解されます (ほとんどの場合、例外がスローされずに LINQ to SQL 式を LINQ to Entities プロバイダーに渡すことはできません)。IQueryable<T>
式は、単にオブジェクト自体の定数式にすることも、クエリ演算子とオペランドで構成されたセットのより複雑なツリーにすることもできます。クエリ プロバイダのIQueryProvider.Execute()またはIQueryProvider.CreateQuery()メソッドがExpressionを渡されて呼び出され、クエリ結果または別の結果IQueryableがそれぞれ返されます。
IQueryable<T>主な違いは、デリゲートではなくオブジェクトを取るための LINQ 演算子ですExpression。つまり、受け取るカスタム クエリ ロジック (述語や値セレクターなど) は、メソッドへのデリゲートではなく、式ツリーの形式です。
IEnumerable<T>メモリ内で反復されるシーケンスを操作するのに最適ですが、IQueryable<T>データベースや Web サービスなどのリモート データ ソースなどのメモリ不足を許容します。クエリの実行が「インプロセス」で実行される場合、通常必要なのは、クエリの各部分を実行するためのコード (コードとして) だけです。
実行がアウトプロセスで実行される場合、クエリのロジックは、LINQ プロバイダーがメモリ不足の実行に適した形式に変換できるように、データで表す必要があります。それが LDAP クエリであるかどうかにかかわらず、 SQLでも何でも。
でより多くの:
IEnumerable<T>およびIQueryable<T>IEnumerable<T>vsIQueryable<T>」IEnumerableおよびのIQueryable紹介IObservableIQbservableIQUERYABLE<T>」Bart De Smetより。
これは、これらのインターフェイスがどのように異なるかを示すyoutubeの素晴らしいビデオで、一見の価値があります。
以下は、それに対する長い説明的な答えです。
覚えておくべき最初の重要なポイントは、IQueryableインターフェースが から継承されIEnumerableているため、できることは何でもIEnumerableできるというIQueryableことです。

多くの違いがありますが、最大の違いを生む 1 つの大きな違いについて説明しましょう。IEnumerableインターフェイスは、LINQまたはエンティティ フレームワークを使用してコレクションが読み込まれ、コレクションにフィルターを適用する場合に便利です。
IEnumerableエンティティ フレームワークを使用する以下の単純なコードを検討してください。Whereフィルターを使用して、が でEmpIdあるレコードを取得してい2ます。
EmpEntities ent = new EmpEntities();
IEnumerable<Employee> emp = ent.Employees;
IEnumerable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>();
この where フィルターは、IEnumerableコードがあるクライアント側で実行されます。言い換えれば、すべてのデータがデータベースから取得され、クライアントでスキャンされ、レコードがEmpIdisで取得されます2。

IEnumerableしかし、次に変更した以下のコードを見てくださいIQueryable。サーバー側でSQLクエリを作成し、必要なデータのみをクライアント側に送信します。
EmpEntities ent = new EmpEntities();
IQueryable<Employee> emp = ent.Employees;
IQueryable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>();

IQueryableしたがって、との違いはIEnumerable、フィルター ロジックが実行される場所に関するものです。1 つはクライアント側で実行され、もう 1 つはデータベースで実行されます。
したがって、インメモリ データ コレクションのみを使用するIEnumerable場合は適切な選択ですが、データベースに接続されたデータ コレクションをクエリする場合は、ネットワーク トラフィックを削減し、SQL 言語の機能を使用するため、IQueryable を使用することをお勧めします。
IEnumerable: IEnumerable は、メモリ内コレクション (またはローカル クエリ) の操作に最適です。IEnumerable は項目間を移動せず、前方のみのコレクションです。
IQueryable: IQueryable は、データベースや Web サービス (またはリモート クエリ) などのリモート データ ソースに最適です。IQueryable は、さまざまな興味深い遅延実行シナリオ (ページングや構成ベースのクエリなど) を可能にする非常に強力な機能です。
したがって、メモリ内コレクションを単純に反復処理する必要がある場合は IEnumerable を使用し、Dataset やその他のデータ ソースなどのコレクションを操作する必要がある場合は IQueryable を使用します。
簡単に言えば、その他の大きな違いは、IEnumerable がサーバー側で選択クエリを実行し、クライアント側でデータをメモリ内にロードしてからデータをフィルタリングし、IQueryable がすべてのフィルターを使用してサーバー側で選択クエリを実行することです。
以下の小さなテストは、 と の違いの 1 つの側面を理解するのに役立つ場合がIQueryable<T>ありIEnumerable<T>ます。他の人の投稿に修正を追加しようとしていたこの投稿からこの回答を再現しました
DB(DDLスクリプト)に次の構造を作成しました:
CREATE TABLE [dbo].[Employee]([PersonId] [int] NOT NULL PRIMARY KEY,[Salary] [int] NOT NULL)
レコード挿入スクリプト (DML スクリプト) は次のとおりです。
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(1, 20)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(2, 30)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(3, 40)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(4, 50)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(5, 60)
GO
今、私の目標はEmployee、データベースのテーブルから上位 2 つのレコードを取得することでした。データベース内のテーブルを指すコンソール アプリケーションに ADO.NET Entity Data Model アイテムを追加し、EmployeeLINQ クエリの作成を開始しました。
IQueryable route のコード:
using (var efContext = new EfTestEntities())
{
IQueryable<int> employees = from e in efContext.Employees select e.Salary;
employees = employees.Take(2);
foreach (var item in employees)
{
Console.WriteLine(item);
}
}
このプログラムの実行を開始したとき、SQL Server インスタンスで SQL Query プロファイラーのセッションも開始しました。実行の概要は次のとおりです。
SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]IQueryableデータベースサーバー側で句を適用するのに十分賢いだけなのでTop (2)、5つのレコードのうち2つだけがネットワーク上にもたらされます。クライアント コンピューター側では、それ以上のメモリ内フィルター処理はまったく必要ありません。
IEnumerable route のコード:
using (var efContext = new EfTestEntities())
{
IEnumerable<int> employees = from e in efContext.Employees select e.Salary;
employees = employees.Take(2);
foreach (var item in employees)
{
Console.WriteLine(item);
}
}
この場合の実行の要約:
SELECT [Extent1].[Salary] AS [Salary]
FROM [dbo].[Employee] AS [Extent1]これで、テーブルにIEnumerable存在する 5 つのレコードがすべてSalary取得され、クライアント コンピューターでインメモリ フィルタリングが実行され、上位 2 つのレコードが取得されます。そのため、より多くのデータ (この場合は 3 つの追加レコード) が不必要にネットワーク経由で転送されました。
IEnumerableはコレクションを参照していますが、IQueryableは単なるクエリであり、式ツリー内で生成されます。このクエリを実行して、データベースからデータを取得します。
と を使用IEnumerableしIQueryableて、データベースから取得したデータを操作します。IQueryableから継承してIEnumerableいるためIQueryable、すべての機能が含まれていIEnumerableます。との主な違いは、IQueryableフィルターを使用してクエリを実行するのに対し、最初にクエリを実行してから、条件に基づいてデータをフィルター処理することです。IEnumerableIQueryableIEnumerable
以下のより詳細な違いを見つけてください:
IEnumerable
IEnumerableSystem.Collections名前空間に存在するIEnumerableサーバー側で選択クエリを実行し、クライアント側でデータをメモリ内にロードしてから、データをフィルタリングしますIEnumerableリスト、配列などのメモリ内コレクションからのデータのクエリに適していますIEnumerableLINQ to Object および LINQ to XML クエリに有益ですIQueryable
IQueryableSystem.Linq名前空間に存在するIQueryableすべてのフィルターを使用してサーバー側で「選択クエリ」を実行しますIQueryableメモリ外 (リモート データベース、サービスなど) のコレクションからのデータのクエリに適しています。IQueryableLINQ to SQL クエリに有益ですsoIEnumerableは通常、メモリ内コレクションを処理するために使用されますが、IQueryableは通常、コレクションを操作するために使用されます。
ienumerable: インプロセス メモリを処理する場合、つまり dataconnection を使用しない場合 iqueryable: SQL サーバーを処理する場合、つまりデータ接続を使用する場合 ilist : オブジェクトの追加、オブジェクトの削除などの操作