チュートリアル: Visual Basic でクエリを記述する
このチュートリアルでは、Visual Basic 言語の機能を使用して 統合言語クエリ (LINQ) クエリ式を記述する方法について説明します。ここでは、Student オブジェクトのリストの作成方法、クエリの実行方法、およびクエリの変更方法を示します。クエリには、オブジェクト初期化子、ローカル型の推論、匿名型など、Visual Basic 2008 で新たに導入された機能が組み込まれています。
このチュートリアルを完了したら、関心のある特定の LINQ プロバイダーのサンプルやドキュメントに進むことができます。LINQ プロバイダーには、LINQ to SQL、LINQ to DataSet、LINQ to XML などがあります。
プロジェクトの作成
コンソール アプリケーション プロジェクトを作成するには
Visual Studio を起動します。
[ファイル] メニューの [新規作成] をポイントし、[プロジェクト] をクリックします。
[インストールされているテンプレート] の [Visual Basic] をクリックします。
プロジェクトの種類の一覧の [コンソール アプリケーション] をクリックします。[プロジェクト名] ボックスにプロジェクトの名前を入力し、[OK] をクリックします。
プロジェクトが作成されます。プロジェクトには、System.Core.dll への参照が既定で含まれます。また、[参照設定] ページ (プロジェクト デザイナー) (Visual Basic) の [インポートされた名前空間] の一覧には、System.Linq 名前空間が含まれます。
[コンパイル] ページ (プロジェクト デザイナー) (Visual Basic)で、[Option Infer] がに設定されていることを確認します。
インメモリ データ ソースの追加
このチュートリアルのクエリのデータ ソースは、Student オブジェクトのリストです。各 Student オブジェクトには、名、姓、学年、および学生全体における成績順位が含まれます。
データ ソースを追加するには
Student クラスを定義し、そのクラスのインスタンスのリストを作成します。
重要 このチュートリアルの例で使用する Student クラスの定義とリストの作成に必要なコードは、「方法: 項目のリストを作成する」に記載されています。そこからコードをコピーし、プロジェクトに貼り付けることができます。プロジェクトの作成時に表示されたコードを、新しいコードで置き換えます。
学生のリストに新しい学生を追加するには
- getStudents メソッドのパターンに従って、Student クラスの別のインスタンスをリストに追加します。学生を追加すると、オブジェクト初期化子が導入されます。詳細については、「オブジェクト初期化子: 名前付きの型と匿名型 (Visual Basic)」を参照してください。
クエリの作成
このセクションで追加したクエリが実行されると、成績順位が上位 10 人に入る学生のリストが生成されます。クエリは毎回完全な Student オブジェクトを選択するので、クエリ結果の型は IEnumerable(Of Student) になります。ただし、通常はクエリ定義にクエリの型を指定することはありません。代わりに、コンパイラがローカル型の推論を使用して型を判断します。詳細については、「ローカル型の推論 (Visual Basic)」を参照してください。クエリの範囲変数である currentStudent は、ソース students 内の各 Student インスタンスへの参照として機能します。これにより、students 内の各オブジェクトのプロパティにアクセスできるようになります。
簡単なクエリを作成するには
プロジェクトの Main メソッドで、次のようにマークされている場所を探します。
' ****Paste query and query execution code from the walkthrough, ' ****or any code of your own, here in Main.
次のコードをコピーして貼り付けます。
Dim studentQuery = From currentStudent In students Where currentStudent.Rank <= 10 Select currentStudent
マウス ポインターをコード内の studentQuery の上に置き、コンパイラが割り当てた型が IEnumerable(Of Student) であることを確認します。
クエリの実行
変数 studentQuery には、クエリの実行結果ではなく、クエリの定義が含まれます。通常、クエリの実行には For Each ループが使用されます。返されたシーケンス内の各要素へは、ループの反復変数を通じてアクセスします。クエリ実行の詳細については、「初めての LINQ クエリの作成 (Visual Basic)」を参照してください。
クエリを実行するには
プロジェクト内のクエリの下に、次の For Each ループを追加します。
For Each studentRecord In studentQuery Console.WriteLine(studentRecord.Last & ", " & studentRecord.First) Next
マウス ポインターをループ制御変数 studentRecord の上に置き、データ型を確認します。studentQuery は Student インスタンスのコレクションを返すので、studentRecord の型は Student であると推論されます。
Ctrl キーを押しながら F5 キーを押して、アプリケーションをビルドおよび実行します。コンソール ウィンドウで結果を確認します。
クエリの変更
クエリ結果が指定した順序で並んでいると、結果のスキャンが簡単になります。使用可能な任意のフィールドに基づいて、返されるシーケンスを並べ替えることができます。
結果を順序に従って並べるには
次の Order By 句を、クエリの Where ステートメントと Select ステートメントの間に追加します。この Order By 句は、結果を各生徒の姓のアルファベット順 (A から Z) に並べます。
Order By currentStudent.Last Ascending
名、姓の順に従って並べるには、両方のフィールドをクエリに追加します。
Order By currentStudent.Last Ascending, currentStudent.First Ascending
Descending を指定すると、Z から A の順に並べることもできます。
Ctrl キーを押しながら F5 キーを押して、アプリケーションをビルドおよび実行します。コンソール ウィンドウで結果を確認します。
ローカル識別子を導入するには
クエリ式にローカル識別子を取り入れるには、このセクションのコードを追加します。ローカル識別子には、中間結果が保持されます。次の例の name は、学生の名前と姓を連結したものを保持する識別子です。ローカル識別子は、利便性のために使用できるほか、式の結果が格納されるので何度も計算を行う必要がなくなり、パフォーマンスの向上につながります。
Dim studentQuery2 = From currentStudent In students Let name = currentStudent.Last & ", " & currentStudent.First Where currentStudent.Year = "Senior" And currentStudent.Rank <= 10 Order By name Ascending Select currentStudent ' If you see too many results, comment out the previous ' For Each loop. For Each studentRecord In studentQuery2 Console.WriteLine(studentRecord.Last & ", " & studentRecord.First) Next
Ctrl キーを押しながら F5 キーを押して、アプリケーションをビルドおよび実行します。コンソール ウィンドウで結果を確認します。
Select 句で 1 つのフィールドを投影するには
ソース内の要素とは異なる要素のシーケンスを生成するクエリを作成するには、このセクションのクエリと For Each ループを追加します。次の例では、ソースは Student オブジェクトのコレクションですが、返されるのは各オブジェクトの 1 つのメンバーだけです。この場合は、Garcia という姓を持つ学生の名だけが返されます。currentStudent.First は文字列なので、studentQuery3 が返すシーケンスのデータ型は IEnumerable(Of String) (文字列のシーケンス) になります。前の例のように、studentQuery3 に対するデータ型の割り当ては、コンパイラによってローカル型の推論を使用して決定されます。
Dim studentQuery3 = From currentStudent In students Where currentStudent.Last = "Garcia" Select currentStudent.First ' If you see too many results, comment out the previous ' For Each loops. For Each studentRecord In studentQuery3 Console.WriteLine(studentRecord) Next
マウス ポインターをコード内の studentQuery3 の上に置き、割り当てられた型が IEnumerable(Of String) であることを確認します。
Ctrl キーを押しながら F5 キーを押して、アプリケーションをビルドおよび実行します。コンソール ウィンドウで結果を確認します。
Select 句で匿名型を作成するには
クエリで匿名型がどのように使用されるかを確認するには、このセクションのコードを追加します。これは、クエリで完全なレコード (前の例の currentStudent レコード) や単一のフィールド (前の例の First) を返すのではなく、データ ソースからいくつかのフィールドを返す場合に使用します。、結果に含めるフィールドを含む新しい名前付きの型を定義する代わりに Select 句でフィールドを指定すると、コンパイラはそれらのフィールドをプロパティとして持つ匿名型を作成します。詳細については、「匿名型 (Visual Basic)」を参照してください。
次の例では、成績順位が 1 位から 10 位までの最上級生の名前と順位を成績順に返すクエリを作成します。この例では、studentQuery4 の型を推論する必要があります。これは、Select 句から返されるのは匿名型のインスタンスであり、匿名型には使用できる名前がないためです。
Dim studentQuery4 = From currentStudent In students Where currentStudent.Year = "Senior" And currentStudent.Rank <= 10 Order By currentStudent.Rank Ascending Select currentStudent.First, currentStudent.Last, currentStudent.Rank ' If you see too many results, comment out the previous ' For Each loops. For Each studentRecord In studentQuery4 Console.WriteLine(studentRecord.Last & ", " & studentRecord.First & ": " & studentRecord.Rank) Next
Ctrl キーを押しながら F5 キーを押して、アプリケーションをビルドおよび実行します。コンソール ウィンドウで結果を確認します。
その他の例
これで基本的な事項は理解できたので、LINQ クエリの柔軟性と利便性を紹介するその他の例の一覧を次に示します。それぞれの例の前には、その動作についての簡単な説明が記載されています。推論された型を確認するために各クエリのクエリ結果変数の上にマウス ポインターを置きます。結果を生成するには、For Each ループを使用します。
' Find all students who are seniors.
Dim q1 = From currentStudent In students
Where currentStudent.Year = "Senior"
Select currentStudent
' Write a For Each loop to execute the query.
For Each q In q1
Console.WriteLine(q.First & " " & q.Last)
Next
' Find all students with a first name beginning with "C".
Dim q2 = From currentStudent In students
Where currentStudent.First.StartsWith("C")
Select currentStudent
' Find all top ranked seniors (rank < 40).
Dim q3 = From currentStudent In students
Where currentStudent.Rank < 40 And currentStudent.Year = "Senior"
Select currentStudent
' Find all seniors with a lower rank than a student who
' is not a senior.
Dim q4 = From student1 In students, student2 In students
Where student1.Year = "Senior" And student2.Year <> "Senior" And
student1.Rank > student2.Rank
Select student1
Distinct
' Retrieve the full names of all students, sorted by last name.
Dim q5 = From currentStudent In students
Order By currentStudent.Last
Select Name = currentStudent.First & " " & currentStudent.Last
' Determine how many students are ranked in the top 20.
Dim q6 = Aggregate currentStudent In students
Where currentStudent.Rank <= 20
Into Count()
' Count the number of different last names in the group of students.
Dim q7 = Aggregate currentStudent In students
Select currentStudent.Last
Distinct
Into Count()
' Create a list box to show the last names of students.
Dim lb As New System.Windows.Forms.ListBox
Dim q8 = From currentStudent In students
Order By currentStudent.Last
Select currentStudent.Last Distinct
For Each nextName As String In q8
lb.Items.Add(nextName)
Next
' Find every process that has a lowercase "h", "l", or "d" in its name.
Dim letters() As String = {"h", "l", "d"}
Dim q9 = From proc In System.Diagnostics.Process.GetProcesses,
letter In letters
Where proc.ProcessName.Contains(letter)
Select proc
For Each proc In q9
Console.WriteLine(proc.ProcessName & ", " & proc.WorkingSet64)
Next
追加情報
クエリの基本的な概念を理解したら、関心のある特定の種類の LINQ プロバイダーのドキュメントやサンプルに進むことができます。
参照
処理手順
概念
オブジェクト初期化子: 名前付きの型と匿名型 (Visual Basic)