IQueryable <T>とIEnumerable <T>の違いは何ですか?


回答:


258

まず、インターフェースを拡張します。「プレーン」で実行できることは何でも、でも実行できます。IQueryable<T> IEnumerable<T>IEnumerable<T>IQueryable<T>

IEnumerable<T>ちょうど持ってGetEnumerator()返すメソッドEnumerator<T>あなたがその呼び出せるためMoveNext()のシーケンスを反復処理する方法をTを

どのようなIQueryable<T>ことはしていIEnumerable<T> ないん特に-1とポイント2つのプロパティで、クエリプロバイダ(例えば、SQLプロバイダへのLINQ)との別のポインティングクエリ式表すIQueryable<T>ことができ、実行時-たどれる抽象構文木などのオブジェクトを指定されたクエリプロバイダーによって理解されます(ほとんどの場合、例外がスローされない限り、LINQ to SQL式をLINQ to Entitiesプロバイダーに渡すことはできません)。

式は、単にオブジェクト自体の定数式、またはクエリ演算子とオペランドの組み合わせセットのより複雑なツリーにすることができます。クエリプロバイダーのIQueryProvider.Execute()またはIQueryProvider.CreateQuery()メソッドは、それに渡される式で呼び出され、クエリ結果または別の結果IQueryableがそれぞれ返されます。


8
AsQueryableを使用するメリットはありますか?
ジョーダン

6
唯一の利点は利便性です。AsQueryable()enumerableをqueryableにキャストし、IQueryableインターフェイスを実装している場合はそれを返します。それ以外の場合ConstantExpressionは、返されたEnumerableQueryオブジェクトで参照されて いるにラップします。
Mark Cidade、2012年



@JenonDリンクが死んでいる、ここwaybackmachineです:web.archive.org/web/20160904162931/http://www.dotnet-tricks.com/...
majjam

201

主な違いは、デリゲートの代わりにオブジェクトをIQueryable<T>受け取るためのLINQ演算子ですExpression。つまり、それが受け取るカスタムクエリロジック(述語や値セレクターなど)は、メソッドへのデリゲートではなく、式ツリーの形式です。

  • IEnumerable<T> インメモリで反復されるシーケンスを操作するのに最適ですが、
  • IQueryable<T> データベースやWebサービスなどのリモートデータソースのようなメモリ不足を可能にします。

クエリ実行:

  • クエリの実行が「インプロセス」で実行される場合、通常必要なのは、クエリの各部分を実行するためのコード(コードとして)だけです。

  • 実行がアウトプロセスで実行される場合、LINQプロバイダーがそれをメモリ不足の実行に適した形式に変換できるように、クエリのロジックをデータで表す必要があります。これがLDAPクエリであっても、 SQLなど。

でより多くの:

http://www.codeproject.com/KB/cs/646361/WhatHowWhere.jpg


14
メモリ不足の操作について言及するのが好きです。それは実際の使用上の違いを明らかにします。
Ishmael Smyrnow

2
IEnumerable <T> Whereメソッドのようにデリゲートをパラメーターとして受け取る代わりに、IQueryable <T>はExpression <TDelegate>パラメーターを受け取ります。IQueryable <T>にコードを渡すのではなく、LINQプロバイダーが分析する式ツリー(データとしてコード)を渡します。C#3.0とLINQ
Lu55 2012年

何かが画像リンクに問題があります。何らかの理由で投稿の本文にレンダリングされません。codeproject.com
KB /

@joeyまだ、私はこの答えでその画像をうまく見ています:i.stack.imgur.com/2DAqv.jpg
VonC

190

これは、これらのインターフェースがどのように異なるかを示すYouTubeの素晴らしいビデオで、一見の価値があります。

以下は、それについての長い説明的な回答です。

最初に覚えておかなければならない重要な点は、IQueryableインターフェイスがから継承することです。IEnumerableそのためIEnumerableIQueryableできることは何でもできます。

ここに画像の説明を入力してください

多くの違いがありますが、最大の違いをもたらす1つの大きな違いについて説明します。IEnumerableインターフェースは、コレクションがLINQやEntityフレームワークを使用して読み込まれ、コレクションにフィルターを適用する場合に便利です。

IEnumerableエンティティフレームワークで使用する以下の単純なコードを考えます。使用していますWhereそのレコードを取得するには、フィルタをEmpIdあるが2

EmpEntities ent = new EmpEntities();
IEnumerable<Employee> emp = ent.Employees; 
IEnumerable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>();

このフィルタは、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の方が適しています。


こんにちは、素晴らしい説明をたくさんありがとう。IQueryableが「メモリ不足」のデータに適している理由を理解していますが、IEnumerableが「メモリ内」のデータに適している理由を理解するのに苦労していますか?それでも、データを取得してフィルターを適用するよりも、フィルターされたデータを取得する方が良いと思います。
Imad

「インメモリ」の場合は、特に問題ではありません。データはすでにメモリ上にあり、フィルタリングされる正確な時間は重要ではありません。
Roni Axelrad

@Imadたとえば、エンティティのDateTimeOffsetをDateTimeに変換してデータを投影することは、IQueryableを使用して、またはEntityFunctionsを使用して実行することはできません。最良の方法は、エンティティオブジェクトをAsEnumerable()にしてから、Select()を使用して、DateTimeを含むビューモデルに入れることです。このプロセスは、メモリ内関数を使用します。
ジェフ

57

IEnumerable: IEnumerableは、メモリ内コレクション(またはローカルクエリ)の操作に最適です。IEnumerableはアイテム間を移動せず、前方のみのコレクションです。

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

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


3
IEnumerableは遅延実行を使用しませんか?
Ian Warburton 2013年

3
遅延実行は、IEnumerableとIQueryableの両方で使用できます。さらに興味深い情報はここで見つけることができます:stackoverflow.com/questions/2876616/...
イグナシオHagopian

18

簡単に言うと、他の大きな違いは、IEnumerableがサーバー側で選択クエリを実行し、クライアント側でメモリ内のデータを読み込んでからデータをフィルターするのに対し、IQueryableはすべてのフィルターを使用してサーバー側で選択クエリを実行することです。


17

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

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

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

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

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

次に、IQueryableを使用すると、生成されたSQLに "where name =" a "が含まれますが、IEnumerableを使用すると、さらに多くのロールがデータベースから取得され、x.name =" a "チェックが.NETによって行われます。


10

IEnumerableはコレクションを参照していますが、IQueryableは単なるクエリであり、式ツリー内で生成されます。このクエリを実行して、データベースからデータを取得します。


8

下記の小さなテストは、IQueryable<T>との違いの1つの側面を理解するのに役立ちます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レコードを取得することでした。Employeeデータベースのテーブルを指すADO.NET Entity Data Modelアイテムをコンソールアプリケーションに追加し、LINQクエリの作成を開始しました。

IQueryableルートのコード

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クエリプロファイラーのセッションも開始していました。実行の概要を次に示します。

  1. 発生したクエリの総数:1
  2. クエリテキスト: SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]

それはそれだけでIQueryable適用するスマート十分であるTop (2)ことはワイヤ上5つのレコードのうちの2つだけをもたらすように、データベース・サーバー側自体に句を。クライアントコンピューター側では、それ以上のインメモリフィルタリングはまったく必要ありません。

IEnumerableルートのコード

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);
    }
}

この場合の実行の概要:

  1. 発生したクエリの総数:1
  2. SQLプロファイラーでキャプチャされたクエリテキスト: SELECT [Extent1].[Salary] AS [Salary] FROM [dbo].[Employee] AS [Extent1]

これで、テーブルにIEnumerable存在する5つのレコードすべてSalaryが取得され、クライアントコンピュータでメモリ内フィルタリングが実行され、上位2つのレコードが取得されました。そのため、より多くのデータ(この場合は3つの追加レコード)が不必要にネットワーク経由で転送されました。


7

これは私が(このトピックについて)同様の投稿で書いたものです。(いいえ、私は通常自分自身を引用しませんが、これらは非常に良い記事です。)

「この記事は役に立ちます: LINQ-to-SQLでのIQueryableとIEnumerableの比較です。

その記事を引用すると、「MSDNドキュメントによると、IQueryableで行われた呼び出しは、代わりに内部式ツリーを構築することによって機能します。「IQueryable(Of T)を拡張するこれらのメソッドは、直接クエリを実行しません。代わりに、それらの機能は、累積クエリを表す式ツリーであるExpressionオブジェクトを構築することです。

式ツリーは、C#および.NETプラットフォームで非常に重要な構成要素です。(それらは一般的に重要ですが、C#はそれらを非常に便利にします。)違いをよりよく理解するために、公式のC#5.0仕様のステートメントの 違いについて読むことをお勧めします。ラムダ計算に分岐する高度な理論的概念の場合、式により、ファーストクラスのオブジェクトとしてのメソッドのサポートが可能になります。IQueryableとIEnumerableの違いは、この点に集中しています。IQueryableは式ツリーを構築しますが、IEnumerableは、少なくともMicrosoftの秘密のラボで作業していない私たちにとってはそうではありません。

ここでは、プッシュとプルの観点からの違いを詳しく説明する、もう1つの非常に役立つ記事を紹介します。(「プッシュ」と「プル」では、データフローの方向を指します。.NETおよびC#のリアクティブプログラミングテクニック

ここでは、ステートメントラムダと式ラムダの違いを詳しく説明し、式の構造の概念をより深く説明する非常に優れた記事を紹介します。C #デリゲート、式ツリー、ラムダステートメントとラムダ式の比較。


6

データベースから取得したデータを使用IEnumerableIQueryableて操作します。IQueryableはから継承するIEnumerableためIQueryable、すべてのIEnumerable機能が含まれます。主な違いIQueryableとはIEnumerableつまりIQueryable、一方、フィルタを使用して実行クエリIEnumerable最初のクエリが実行され、それが条件に基づいてデータをフィルタリングします。

以下のより詳細な差別化を見つけてください:

IEnumerable

  1. IEnumerableSystem.Collections名前空間に存在する
  2. IEnumerable サーバー側で選択クエリを実行し、クライアント側でメモリ内のデータを読み込み、データをフィルター処理する
  3. IEnumerable List、Arrayなどのメモリ内コレクションからのデータのクエリに適しています
  4. IEnumerable LINQ to ObjectおよびLINQ to XMLクエリに有益

IQueryable

  1. IQueryableSystem.Linq名前空間に存在する
  2. IQueryable すべてのフィルターを使用してサーバー側で「選択クエリ」を実行します
  3. IQueryable アウトメモリ(リモートデータベース、サービスなど)コレクションからのデータのクエリに適しています
  4. IQueryable LINQ to SQLクエリに有益

したがってIEnumerable、通常はメモリ内コレクションのIQueryable処理に使用されますが、コレクションの操作には一般的に使用されます。



2

データベースから大量のデータを処理している場合、IQueryableはIEnumerableよりも高速です。これは、IQueryableが必要なデータのみをデータベースから取得するため、IEnumerableがデータベースの必要性に関係なくすべてのデータを取得するためです。


0

ienumerable:インプロセスメモリを処理する場合、つまりデータ接続なしiqueryable:SQLサーバーを処理する場合、つまりデータ接続ilistを使用する場合:オブジェクトの追加、オブジェクトの削除などの操作

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.