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
紹介IObservable
IQbservable
IQUERYABLE<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
コードがあるクライアント側で実行されます。言い換えれば、すべてのデータがデータベースから取得され、クライアントでスキャンされ、レコードがEmpId
isで取得されます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 アイテムを追加し、Employee
LINQ クエリの作成を開始しました。
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
フィルターを使用してクエリを実行するのに対し、最初にクエリを実行してから、条件に基づいてデータをフィルター処理することです。IEnumerable
IQueryable
IEnumerable
以下のより詳細な違いを見つけてください:
IEnumerable
IEnumerable
System.Collections
名前空間に存在するIEnumerable
サーバー側で選択クエリを実行し、クライアント側でデータをメモリ内にロードしてから、データをフィルタリングしますIEnumerable
リスト、配列などのメモリ内コレクションからのデータのクエリに適していますIEnumerable
LINQ to Object および LINQ to XML クエリに有益ですIQueryable
IQueryable
System.Linq
名前空間に存在するIQueryable
すべてのフィルターを使用してサーバー側で「選択クエリ」を実行しますIQueryable
メモリ外 (リモート データベース、サービスなど) のコレクションからのデータのクエリに適しています。IQueryable
LINQ to SQL クエリに有益ですsoIEnumerable
は通常、メモリ内コレクションを処理するために使用されますが、IQueryable
は通常、コレクションを操作するために使用されます。
ienumerable: インプロセス メモリを処理する場合、つまり dataconnection を使用しない場合 iqueryable: SQL サーバーを処理する場合、つまりデータ接続を使用する場合 ilist : オブジェクトの追加、オブジェクトの削除などの操作