クエリは、データ ソースからデータを取得する式です。 クエリは専用のクエリ言語で表されます。 時間の経過とともに、リレーショナル データベース用の SQL や XML 用の XQuery など、さまざまな種類のデータ ソースに対してさまざまな言語が開発されています。 これにより、アプリケーション開発者は、サポートされているデータ ソースまたはデータ形式の種類ごとに新しいクエリ言語を学習する必要があります。
Language-Integrated クエリ (LINQ) は、さまざまな種類のデータ ソースと形式にわたってデータを操作するための一貫したモデルを提供することで、状況を簡略化します。 LINQ クエリでは、常にオブジェクトを操作します。 同じ基本的なコーディング パターンを使用して、XML ドキュメント、SQL データベース、ADO.NET データセットとエンティティ、.NET Framework コレクション、および LINQ プロバイダーが使用できるその他のソースまたは形式のデータのクエリと変換を行います。 このドキュメントでは、基本的な LINQ クエリの作成と使用の 3 つのフェーズについて説明します。
クエリ操作の 3 つのステージ
LINQ クエリ操作は、次の 3 つのアクションで構成されます。
データ ソースまたはソースを取得します。
クエリを作成します。
クエリを実行します。
LINQ では、クエリの実行はクエリの作成とは異なります。 クエリを作成するだけでデータを取得することはありません。 この点については、このトピックの後半で詳しく説明します。
次の例は、クエリ操作の 3 つの部分を示しています。 この例では、デモンストレーション用の便利なデータ ソースとして整数の配列を使用しています。 ただし、他のデータ ソースにも同じ概念が適用されます。
注
[ コンパイル] ページのプロジェクト デザイナー (Visual Basic)で、オプション推論 が [オン] に設定されていることを確認します。
' Data source.
Dim numbers() As Integer = {0, 1, 2, 3, 4, 5, 6}
' Query creation.
Dim evensQuery = From num In numbers
Where num Mod 2 = 0
Select num
' Query execution.
For Each number In evensQuery
Console.Write(number & " ")
Next
アウトプット:
0 2 4 6
データ ソース
前の例のデータ ソースは配列であるため、ジェネリック IEnumerable<T> インターフェイスを暗黙的にサポートしています。 このため、LINQ クエリのデータ ソースとして配列を使用できます。 IEnumerable<T>またはジェネリック IQueryable<T>などの派生インターフェイスをサポートする型は、クエリ可能な型と呼ばれます。
暗黙的にクエリ可能な型として、配列は LINQ データ ソースとして機能するために変更や特別な処理を必要としません。 .NET Framework クラス ライブラリのジェネリック List<T>、Dictionary<TKey,TValue>、その他のクラスなど、IEnumerable<T>をサポートするコレクション型についても同様です。
ソース データに IEnumerable<T>がまだ実装されていない場合は、そのデータ ソースの 標準クエリ演算子 の機能を実装するために LINQ プロバイダーが必要です。 たとえば、LINQ to XML は、次の例に示すように、クエリ可能な XElement 型に XML ドキュメントを読み込む処理を処理します。 標準クエリ演算子の詳細については、「 標準クエリ演算子の概要 (Visual Basic)」を参照してください。
' Create a data source from an XML document.
Dim contacts = XElement.Load("c:\myContactList.xml")
LINQ to SQL では、まず、手動で、または Visual Studio の Visual Studio で LINQ to SQL Tools を使用して、デザイン時にオブジェクト リレーショナル マッピングを作成します。 オブジェクトに対してクエリを記述すると、実行時に LINQ to SQL がデータベースとの通信を処理します。 次の例では、 customers
はデータベース内の特定のテーブルを表し、 Table<TEntity> は汎用 IQueryable<T>をサポートしています。
' Create a data source from a SQL table.
Dim db As New DataContext("C:\Northwind\Northwnd.mdf")
Dim customers As Table(Of Customer) = db.GetTable(Of Customer)
特定の種類のデータ ソースを作成する方法の詳細については、さまざまな LINQ プロバイダーのドキュメントを参照してください。 (これらのプロバイダーの一覧については、 LINQ (Language-Integrated クエリ) を参照してください)。 基本的なルールは単純です。LINQ データ ソースは、ジェネリック IEnumerable<T> インターフェイス、またはそのインターフェイスから継承するインターフェイスをサポートする任意のオブジェクトです。
注
非ジェネリック IEnumerable インターフェイスをサポートするArrayListなどの型は、LINQ データ ソースとしても使用できます。 ArrayListを使用する例については、「方法: LINQ を使用して ArrayList にクエリを実行する (Visual Basic)」を参照してください。
クエリ
クエリでは、データ ソースまたはソースから取得する情報を指定します。 また、情報を返す前に、その情報を並べ替え、グループ化、または構造化する方法を指定することもできます。 クエリの作成を有効にするために、Visual Basic では新しいクエリ構文が言語に組み込まれています。
実行されると、次の例のクエリは整数配列からすべての偶数を返します( numbers
)。
' Data source.
Dim numbers() As Integer = {0, 1, 2, 3, 4, 5, 6}
' Query creation.
Dim evensQuery = From num In numbers
Where num Mod 2 = 0
Select num
' Query execution.
For Each number In evensQuery
Console.Write(number & " ")
Next
クエリ式には、 From
、 Where
、 Select
の 3 つの句が含まれています。 各クエリ式句の特定の関数と目的については、 基本的なクエリ操作 (Visual Basic) で説明します。 詳細については、「 クエリ」を参照してください。 LINQ では、多くの場合、クエリ定義は変数に格納され、後で実行されることに注意してください。 前の例の evensQuery
などのクエリ変数は、クエリ可能な型である必要があります。
evensQuery
の型はIEnumerable(Of Integer)
され、ローカル型推論を使用してコンパイラによって割り当てられます。
クエリ変数自体はアクションを実行せず、データを返さないことを覚えておく必要があります。 クエリ定義のみが格納されます。 前の例では、クエリを実行する For Each
ループです。
クエリの実行
クエリの実行は、クエリの作成とは別です。 クエリの作成によってクエリが定義されますが、実行は別のメカニズムによってトリガーされます。 クエリは、定義が定義されるとすぐに実行できます (即時実行)、または定義を格納して、後でクエリを実行できます (遅延実行)。
遅延実行
一般的な LINQ クエリは、 evensQuery
が定義されている前の例に似ています。 クエリは作成されますが、すぐには実行されません。 代わりに、クエリ定義はクエリ変数 evensQuery
に格納されます。 クエリは後で実行します。通常は、値のシーケンスを返す For Each
ループを使用するか、 Count
や Max
などの標準クエリ演算子を適用します。 このプロセスは、 遅延実行と呼ばれます。
' Query execution that results in a sequence of values.
For Each number In evensQuery
Console.Write(number & " ")
Next
' Query execution that results in a single value.
Dim evens = evensQuery.Count()
値のシーケンスの場合は、 For Each
ループの反復変数 (前の例でnumber
) を使用して、取得したデータにアクセスします。 クエリ変数 evensQuery
はクエリ結果ではなくクエリ定義を保持するため、クエリ変数を複数回使用して必要な頻度でクエリを実行できます。 たとえば、アプリケーション内に、別のアプリケーションによって継続的に更新されるデータベースがあるとします。 そのデータベースからデータを取得するクエリを作成したら、 For Each
ループを使用してクエリを繰り返し実行し、毎回最新のデータを取得できます。
次の例は、遅延実行のしくみを示しています。 前の例と同様に、 evensQuery2
が定義され、 For Each
ループで実行されると、データ ソース numbers
の一部の要素が変更されます。 その後、2 つ目の For Each
ループが再び evensQuery2
実行されます。
For Each
ループはクエリを再度実行し、numbers
の新しい値を使用するため、2 回目は結果が異なります。
Dim numberArray() = {0, 1, 2, 3, 4, 5, 6}
Dim evensQuery2 = From num In numberArray
Where num Mod 2 = 0
Select num
Console.WriteLine("Evens in original array:")
For Each number In evensQuery2
Console.Write(" " & number)
Next
Console.WriteLine()
' Change a few array elements.
numberArray(1) = 10
numberArray(4) = 22
numberArray(6) = 8
' Run the same query again.
Console.WriteLine(vbCrLf & "Evens in changed array:")
For Each number In evensQuery2
Console.Write(" " & number)
Next
Console.WriteLine()
アウトプット:
Evens in original array:
0 2 4 6
Evens in changed array:
0 10 2 22 8
即時実行
クエリの遅延実行では、クエリ定義は後で実行するためにクエリ変数に格納されます。 即時実行では、クエリは定義時に実行されます。 クエリ結果の個々の要素へのアクセスを必要とするメソッドを適用すると、実行がトリガーされます。 多くの場合、1 つの値を返す標準クエリ演算子の 1 つを使用して、即時実行が強制されます。 たとえば、 Count
、 Max
、 Average
、 First
などです。 これらの標準クエリ演算子は、単一の結果を計算して返すために、適用されるとすぐにクエリを実行します。 単一値を返す標準クエリ演算子の詳細については、「 集計操作、 要素操作、 量指定子操作」を参照してください。
次のクエリは、整数の配列内の偶数の数を返します。 クエリ定義は保存されず、 numEvens
は単純な Integer
です。
Dim numEvens = (From num In numbers
Where num Mod 2 = 0
Select num).Count()
Aggregate
メソッドを使用すると、同じ結果を得ることができます。
Dim numEvensAgg = Aggregate num In numbers
Where num Mod 2 = 0
Select num
Into Count()
次のコードに示すように、クエリ (即時) またはクエリ変数 (遅延) に対して ToList
または ToArray
メソッドを呼び出すことによって、クエリの実行を強制することもできます。
' Immediate execution.
Dim evensList = (From num In numbers
Where num Mod 2 = 0
Select num).ToList()
' Deferred execution.
Dim evensQuery3 = From num In numbers
Where num Mod 2 = 0
Select num
' . . .
Dim evensArray = evensQuery3.ToArray()
前の例では、 evensQuery3
はクエリ変数ですが、 evensList
はリストであり、 evensArray
は配列です。
ToList
またはToArray
を使用して即時実行を強制することは、クエリを直ちに実行し、結果を単一のコレクション オブジェクトにキャッシュするシナリオで特に便利です。 これらのメソッドの詳細については、「 データ型の変換」を参照してください。
IEnumerable.GetEnumerator メソッドなどのIEnumerable
メソッドを使用してクエリを実行することもできます。
こちらも参照ください
.NET