LINQ to Entities をいつ使用IEnumerable
する必要があるかについて、理解を深めたいと考えています。IQueryable
データベースへの本当に基本的な呼び出しを使用すると、はるかに高速になりますIQueryable
が、代わりに を使用することをいつ考える必要がありますIEnumerable
か?
??に対するIEnumerable
最適な値はどこにありますか?IQueryable
LINQ to Entities をいつ使用IEnumerable
する必要があるかについて、理解を深めたいと考えています。IQueryable
データベースへの本当に基本的な呼び出しを使用すると、はるかに高速になりますIQueryable
が、代わりに を使用することをいつ考える必要がありますIEnumerable
か?
??に対するIEnumerable
最適な値はどこにありますか?IQueryable
基本的に、IQueryables はクエリ プロバイダー (データベースなど) によって実行され、一部の操作はデータベースによって実行できない、または実行すべきではありません。たとえば、データベースから取得した値を使用して C# 関数 (ここでは例として、名前を正しく大文字にします) を呼び出したい場合は、次のようなことを試してください。
db.Users.Select(x => Capitalize(x.Name)) // Tries to make the db call Capitalize.
.ToList();
はSelect
IQueryable で実行され、基になるデータベースはCapitalize
関数を認識しないため、クエリは失敗します。代わりにできることは、データベースから正しいデータを取得し、IQueryable を IEnumerable に変換して (これは基本的にメモリ内のコレクションを反復処理する方法にすぎません)、残りの操作をローカル メモリ内で行うことです。
db.Users.Select(x => x.Name) // Gets only the name from the database
.AsEnumerable() // Do the rest of the operations in memory
.Select(x => Capitalize(x)) // Capitalize in memory
.ToList();
EF 側から見た IQueryable と IEnumerable のパフォーマンスに関して最も重要なことは、常に IQueryableを使用してデータをフィルター処理し、IEnumerable に変換するデータをできるだけ少なくすることです。呼び出しが基本的に行うことAsEnumerable
は、データベースに「現在フィルター処理されているデータを提供してください」と伝えることです。フィルター処理を行わなかった場合は、必要のないデータであっても、すべてがメモリにフェッチされます。
IEnumerable
必要な答えが見つかるまで 1 つずつ列挙する一連の要素を表します。たとえば、10 を超えるプロパティを持つすべてのエンティティが必要な場合は、それぞれを順番に調べて、それらだけを返す必要があります。それが一致しました。これを行うために、データベース テーブルのすべての行をメモリにプルすることは、おそらく良い考えではありません。
IQueryable
一方、フィルタリングなどの操作を基になるデータ ソースに任せることができる要素のセットを表すため、フィルタリングの場合、IQueryable
カスタム データ ソースの上に実装する (または LINQ to Entities を使用する) 場合は、データ ソース (データベースなど) のフィルタリングやグループ化などの大変な作業を行うことができます。
の主な欠点IQueryable
は、実装がかなり難しいことです。クエリは式ツリーとして構築され、実装者としてクエリを解決するために解析する必要があります。ただし、プロバイダーを作成する予定がない場合は、これで問題はありません。
知っておく価値のある IQueryable のもう 1 つの側面 (これは実際には、世界について異なる仮定を行う可能性のある別のシステムに処理を渡すことに関する一般的な注意事項にすぎません) は、文字列比較のようなものがそのままの方法で機能することを見つけることができるということです。たとえば、ソース データベースでは大文字と小文字が区別されないが、.NET でのデフォルトの比較では大文字と小文字が区別される場合などです。