web-dev-qa-db-ja.com

コレクションで本当にAsQueryable()を使用する必要がありますか?

コード例:

List<Student> Students = new List<Student>()   
{   
    new Student(101, "Hugo", "Garcia", new List<int>() { 91, 88, 76, 93 }),  
    new Student(102, "Rick", "Adams", new List<int>() { 70, 73, 66, 90 }),  
    new Student(103, "Michael", "Tucker", new List<int>() { 73, 80, 75, 88 }),  
    new Student(104, "Fadi", "Fakhouri", new List<int>() { 82, 75, 66, 84 }),  
    new Student(105, "Peter", "Barrows", new List<int>() { 67, 78, 70, 82 })  
};

var query = from student in Students
            where student.Marks.AsQueryable().All(m => m > 70)
            select student;

foreach (Student student in query)
{
    Console.WriteLine("{0} {1}<br />", student.FirstName, student.LastName);
}

しかし、クエリをに変更すると

var query = from student in Students
            where student.Marks.All(m => m > 70)
            select student;

これも機能し、同じ結果を生成しますが、違いは何ですか?

14
Cheung

IQueryableは、(データベースなどの)リモートソースからのオブジェクトに必要/推奨されます。

メモリ内のコレクションの場合、それは役に立ちません。

AsQueryable は、式ツリーを作成するときに使用されます。

最適なシナリオが思い浮かびます。あなたの例では、学生IDに基づいてデータベースからいくつかの情報が必要だとします。

現在、学生はメモリコレクションにいます。学生IDに基づいてデータベースクエリを実行する必要があります。

  var studentList = Students.Select(s => s.Id).AsQueryAble().Select(i => remoteDBProvider.GetInfo(i));

StudentListに対するそれ以上の操作は、IQueryAbleインターフェイス(クエリ式)から呼び出され、データソースからそれらのレコードのみをフェッチします。これは、最終的なクエリ結果として返されます(データソースである限り、remoteDBProvider.GetInfoの戻り値この例では、 QueryProvider )をサポートしています。

8
Tilak

式ツリーの構築方法を実行する必要があります。これを見てください:

AsQueryableは、クエリをIQueryableのインスタンスに変換できるようにするメソッドです。既存のクエリでAsQueryable演算子を使用し、フィルターの適用や並べ替え順序の指定などの変換をさらに適用すると、それらのラムダステートメントは式ツリーに変換されます。使用しているプロバイダーに応じて、式ツリーはドメイン固有の構文に変換されてから実行されます。 Linq to SQLプロバイダーの場合、式ツリーはSQLに変換され、SQLサーバーで実行されます。ただし、IQueryableを実装せず、IEnumerableのみを実装するクエリでAsQueryable演算子を使用する場合、クエリに適用する変換は自動的にIEnumerable仕様にフォールバックします。これが意味するのは、クエリにAsQueryableのタグを付けることで、Linq toSQLとLinqtoobjectの実装の両方のメリットが得られるということです。既存のクエリがたまたまIQueryableを実装している場合、クエリはLinq to SQLプロバイダーによってSQLに変換されます。それ以外の場合、クエリはメモリ内でILコードの形式で実行されます。

参照 ここ

2
Arion

_List<Student>_の場合、返された_IQueryable<T>_は、使用しなかった場合と同じメソッドを使用してクエリを実行するため、違いはありません AsQueryable() まったく。

一部のメソッドは _IQueryable<T>_ パラメーターを必要とします。 AsQueryable()拡張メソッドは、_IQueryable<T>_を渡す必要があるが、_IEnumerable<T>_しかない場合に、これらのシナリオで最も役立つと思います。

MSDNはAsQueryableについて述べています:

ソースのタイプが_IQueryable<T>_を実装している場合、AsQueryable<TElement>(IEnumerable<TElement>)はそれを直接返します。それ以外の場合は、Enumerableの代わりにQueryableの同等のクエリ演算子メソッドを呼び出すことによってクエリを実行する_IQueryable<T>_を返します。

つまり、あなたの場合(_List<T>_は_IQueryable<T>_を実装していません)、実際にはAsQueryableは必要ありません。

2
Botz3000