연습: Visual Basic에서 쿼리 작성
업데이트: 2007년 11월
이 연습에서는 새 Visual Basic 2008 언어 기능을 안내하고 이러한 기능을 사용하여 LINQ(통합 언어 쿼리) 쿼리 식을 작성하는 과정을 설명합니다. 이 연습에서는 Student 개체 목록에 대한 쿼리를 만들어 실행하고 수정하는 방법을 보여 줍니다. 이 쿼리는 개체 이니셜라이저, 로컬 형식 유추 및 익명 형식을 비롯한 Visual Basic 2008의 여러 새 기능을 통합합니다.
이 연습을 마치고 나면 원하는 특정 LINQ 공급자에 대한 샘플과 설명서를 진행해도 좋습니다. LINQ 공급자에는 LINQ to SQL, LINQ to DataSet 및 LINQ to XML이 포함됩니다.
비디오 데모를 보려면 Video How to: Writing Queries in Visual Basic을 참조하십시오.
프로젝트 만들기
.NET Framework 버전 3.5 이상을 대상으로 하는 프로젝트를 만들려면
Visual Studio 2008을 시작합니다.
파일 메뉴에서 새 프로젝트를 클릭합니다.
콘솔 응용 프로그램을 클릭하고 확인을 클릭합니다.
프로젝트가 만들어집니다. 기본적으로 프로젝트에는 System.Core.dll에 대한 참조와 System.Linq 네임스페이스에 대한 Imports 문이 포함되며 LINQ 쿼리를 실행하려면 둘 다 필요합니다.
메모리 내 데이터 소스 추가
이 연습에서 쿼리의 데이터 소스는 Student 개체 목록입니다. 각 Student 개체는 이름, 성, 학년 및 전교 등수를 포함합니다.
데이터 소스를 추가하려면
Student 클래스를 정의하고 이 클래스의 인스턴스 목록을 만듭니다.
중요: 연습 예제에서 사용된 목록을 만들고 Student 클래스를 정의하는 데 필요한 코드는 방법: 항목 목록 만들기에서 제공됩니다. 이 코드를 복사하여 프로젝트에 붙여넣을 수 있습니다. 프로젝트를 만들 때 표시된 코드는 새 코드로 대체됩니다.
새 학생을 학생 목록에 추가하려면
- getStudents 메서드의 패턴에 따라 Student 클래스의 다른 인스턴스를 목록에 추가합니다. 학생을 추가하면 Visual Basic 2008의 새로운 기능인 개체 이니셜라이저로 이동하게 됩니다. 자세한 내용은 개체 이니셜라이저: 명명된 형식과 익명 형식을 참조하십시오.
쿼리 만들기
이 섹션에서 추가된 쿼리는 실행될 경우 등수가 10등 안에 드는 학생 목록을 생성합니다. 쿼리가 매번 완전한 Student 개체를 선택하기 때문에 쿼리 결과의 형식은 IEnumerable(Of Student)입니다. 그러나 쿼리의 형식은 일반적으로 쿼리 정의에 지정되지 않습니다. 대신에 컴파일러는 로컬 형식 유추를 사용하여 형식을 결정합니다. 자세한 내용은 지역 형식 유추를 참조하십시오. 쿼리의 범위 변수인 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를 눌러 응용 프로그램을 빌드하고 실행합니다. 콘솔 창의 결과를 확인합니다.
쿼리 수정
쿼리 결과는 지정된 순서로 되어 있는 경우 더 쉽게 검색할 수 있습니다. 사용할 수 있는 모든 필드에 기초하여 반환된 시퀀스를 정렬할 수 있습니다.
결과의 순서를 지정하려면
쿼리의 Where 문과 Select 문 사이에 다음 Order By 절을 추가합니다. Order By 절은 각 학생의 성에 따라 사전순으로 A부터 Z까지 결과의 순서를 지정합니다.
Order By currentStudent.Last Ascending _
성과 이름별로 차례로 순서를 지정하려면 두 필드를 쿼리에 모두 추가합니다.
Order By currentStudent.Last Ascending, currentStudent.First Ascending _
Z에서 A로 순서를 지정하기 위해 Descending을 지정할 수도 있습니다.
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 절에서 하나의 필드를 반환하려면
이 섹션의 쿼리와 For Each 루프를 추가하여 해당 요소가 소스의 요소와 다른 시퀀스를 생성하는 쿼리를 만듭니다. 다음 예제에서 소스는 Student 개체의 컬렉션이지만 각 개체의 한 멤버, 즉 성이 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 절에서 익명 형식을 만들려면
이 섹션의 코드를 추가하여 쿼리에서 익명 형식이 사용되는 방법을 확인합니다. 익명 형식은 Visual Basic 2008의 새 기능입니다. 완전한 레코드(이전 예제의 currentStudent 레코드) 또는 단일 필드(이전 섹션의 First) 대신에 데이터 소스의 여러 필드를 반환하려면 쿼리에서 익명 형식을 사용합니다. 결과에 포함할 필드가 들어 있는 명명된 형식을 새로 정의하는 대신 Select 절에서 필드를 지정합니다. 그러면 컴파일러는 이러한 필드를 속성으로 가지는 익명 형식을 만듭니다. 자세한 내용은 익명 형식을 참조하십시오.
다음 예제는 등수에 따라 1등에서 10등 사이에 있는 상급생의 이름과 등수를 반환하는 쿼리를 만듭니다. 이 예제에서 Select 절이 익명 형식의 인스턴스를 반환하고 사용할 수 있는 이름이 익명 형식에 없으므로 studentQuery4의 형식이 유추되어야 합니다.
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 공급자 형식에 대한 설명서와 샘플을 읽어도 좋습니다.