最初に
本記事は「Effective C#」で得た知見である、IEnumerable<T>
とIQueryable<T>
の違いについて解説したものとなります。
何番煎じとか知らない。
何となくで理解していたところだったので改めてしっかりと学んでみたいと思います。
LINQプロバイダー
標準クエリ演算子を実装しているライブラリのことをLINQプロバイダーと呼びます。もちろん.NET標準ライブラリではIEnumerable<T>
とIQueryable<T>
の二つのインターフェイスに対して標準クエリ演算子の実装が存在しています。
IEnumerable
IEnumerable
は内部加工方式を取る場合に使用します。内部加工方式とは、データ全件をどこからか受け取った後、ローカル上でクエリを動作させてデータを加工することを指します。
IEnumerable<T>
のクエリ式を実装している(つまり拡張メソッド)のは**System.Linq.Enumerable
になります。拡張メソッド群はLINQ to Objects**とも呼ばれています。.NETのコレクションもほとんどがIEnumerable<T>
を実装しています。
↓拡張メソッド一覧(公式)↓
https://docs.microsoft.com/ja-jp/dotnet/api/system.linq.enumerable?view=netframework-4.7.2
IEnumerable<T>
の実装メソッドはクエリ式中のラムダ式を関数引数として扱うことができるように、デリゲートを使用しています。
IEnumerableはメモリ内のコレクションを繰り返し処理するのに適しています。
IQueryable
IQueryable
は外部クエリ方式を取る場合に使用します。外部クエリ方式とは、クエリを外部のサーバーへ投げて、サーバー上でそのクエリを使用してデータを加工してもらい、加工結果だけを受け取ることを指します。
IQueryable
はIEnumerable
を継承しているので互換性はありますが、シーケンス同士にも互換性があるとは限りません。
IQueryable<T>
のクエリ式を実装しているのは**System.Linq.Queryable
**になります。
↓拡張メソッド一覧(公式)↓
https://docs.microsoft.com/ja-jp/dotnet/api/system.linq.queryable?view=netframework-4.7.2
IQueryable<T>
のクエリ式はまず式ツリー(expression tree)として処理します。そのあとにSQLへと変換され、サーバー上で実行されます。式ツリーとは、ラムダ式をクエリの動作を表すロジックのデータとして受け取るための機能です。
IQueryableはデータベースなどのデータを処理するのに適しています。
二つの使い分け
IEnumerableはローカル上で実行されるため、処理対象のデータをどこか別の場所から持ってくる必要があります。ここで、サーバ等から全件を貰うなどと言うような通信をすると、非常に多くのデータを転送することになる上に不必要なデータまで貰い、余分な処理も行うためボトルネックとなってしまいます。
データを持っているサーバーがRDBのように、高度なクエリを受け付けてくれる場合は外部クエリ方式(IQueryable)を使用した方が良い性能を得られます。
ところでこの二つのハイブリットに当たるAsEnumerable
と言う機能もあるのですが、それはまた別の機会に。