연습: Visual Basic에서 쿼리 작성

이 연습에서는 Visual Basic 언어 기능을 사용하여 LINQ(Language-Integrated Query) 쿼리 식을 작성하는 방법을 보여 줍니다. 이 연습에서는 Student 개체 목록에서 쿼리를 만드는 방법, 쿼리를 실행하는 방법 및 쿼리를 수정하는 방법을 보여 줍니다. 쿼리는 개체 이니셜라이저, 로컬 형식 유추 및 익명 형식을 비롯한 여러 기능을 통합합니다.

이 연습을 완료하면 관심 있는 특정 LINQ 공급자에 대한 샘플 및 설명서로 이동할 준비가 됩니다. LINQ 공급자에는 LINQ to SQL, LINQ to DataSet 및 LINQ to XML이 포함됩니다.

프로젝트 만들기

콘솔 애플리케이션 프로젝트를 만들려면

  1. Visual Studio를 시작합니다.

  2. 파일 메뉴에서 새로 만들기를 가리킨 다음 프로젝트를 클릭합니다.

  3. 설치된 템플릿 목록에서 Visual Basic을 클릭합니다.

  4. 프로젝트 형식 목록에서 콘솔 애플리케이션을 클릭합니다. 이름 상자에 프로젝트의 이름을 입력한 다음 확인을 클릭합니다.

    프로젝트가 만들어집니다. 기본적으로 System.Core.dll 대한 참조가 포함됩니다. 또한 참조 페이지, 프로젝트 디자이너(Visual Basic)가져온 네임스페이스 목록에는 System.Linq 네임스페이스가 포함됩니다.

  5. 컴파일 페이지의 프로젝트 디자이너(Visual Basic)에서 옵션 유추켜짐으로 설정되어 있는지 확인합니다.

메모리 내 데이터 원본 추가

이 연습에서 쿼리의 데이터 원본은 Student 개체의 목록입니다. 각 Student 개체에는 학생 본문의 이름, 성, 수업 연도 및 학업 순위가 포함됩니다.

데이터 소스를 추가하려면

  • Student 클래스를 정의하고 클래스의 인스턴스 목록을 만듭니다.

    Important

    Student 클래스를 정의하고 연습 예제에 사용된 목록을 만드는 데 필요한 코드는 방법: 항목 목록 만들기에 제공됩니다. 여기에서 복사하여 프로젝트에 붙여넣을 수 있습니다. 새 코드는 프로젝트를 만들 때 나타나는 코드를 대체합니다.

학생 목록에 새 학생을 추가하려면

쿼리 만들기

실행될 때 이 섹션에 추가된 쿼리는 학업 순위가 상위 10위 안에 들어 있는 학생 목록을 생성합니다. 쿼리는 매번 전체 Student 개체를 선택하므로 쿼리 결과의 형식은 IEnumerable(Of Student)입니다. 그러나 쿼리 형식은 일반적으로 쿼리 정의에 지정되지 않습니다. 대신 컴파일러는 로컬 형식 유추를 사용하여 형식을 확인합니다. 자세한 내용은 지역 형식 유추를 참조하세요. 쿼리의 범위 변수인 currentStudent은 소스 students에서 각 Student인스턴스에 대한 참조 역할을 하며 students에서 각 개체의 속성에 대한 액세스를 제공합니다.

단순 쿼리를 작성하려면

  1. 다음과 같이 표시된 프로젝트의 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
    
  2. 코드의 studentQuery 마우스 포인터를 놓아 컴파일러 할당 형식이 IEnumerable(Of Student)인지 확인합니다.

쿼리 실행

studentQuery 변수에는 쿼리 실행 결과가 아니라 쿼리 정의가 포함됩니다. 쿼리를 실행하는 일반적인 메커니즘은 For Each 루프입니다. 반환된 시퀀스의 각 요소는 루프 반복 변수를 통해 액세스됩니다. 쿼리 실행에 대한 자세한 내용은 첫 번째 LINQ 쿼리 작성을 참조하세요.

쿼리를 실행하려면

  1. 프로젝트의 쿼리 아래에 다음 For Each 루프를 추가합니다.

    For Each studentRecord In studentQuery
        Console.WriteLine(studentRecord.Last & ", " & studentRecord.First)
    Next
    
  2. 루프 컨트롤 변수 studentRecord에 마우스 포인터를 놓아 데이터 형식을 확인합니다. studentQueryStudent 인스턴스의 컬렉션을 반환하기 때문에 studentRecord 형식이 Student로 유추됩니다.

  3. Ctrl+F5를 눌러 애플리케이션을 빌드하고 실행합니다. 콘솔 창의 결과를 확인합니다.

쿼리 수정

지정된 순서로 쿼리 결과를 검색하는 것이 더 쉽습니다. 사용 가능한 필드를 기준으로 반환된 시퀀스를 정렬할 수 있습니다.

결과를 정렬하려면

  1. Where 문과 쿼리의 Select 문 사이에 다음 Order By 절을 추가합니다. Order By 절은 각 학생의 성을 기준으로 결과를 A에서 Z로 사전순으로 정렬합니다.

    Order By currentStudent.Last Ascending
    
  2. 성을 순서대로 정렬한 다음 이름을 지정하려면 두 필드를 쿼리에 추가합니다.

    Order By currentStudent.Last Ascending, currentStudent.First Ascending
    

    Descending을 지정하여 Z에서 A로 정렬할 수도 있습니다.

  3. Ctrl+F5를 눌러 애플리케이션을 빌드하고 실행합니다. 콘솔 창의 결과를 확인합니다.

로컬 식별자를 소개하려면

  1. 이 섹션의 코드를 추가하여 쿼리 식에 로컬 식별자를 소개합니다. 로컬 식별자는 중간 결과를 보유합니다. 다음 예제에서 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
    
  2. Ctrl+F5를 눌러 애플리케이션을 빌드하고 실행합니다. 콘솔 창의 결과를 확인합니다.

Select 절에서 하나의 필드를 프로젝트하려면

  1. 이 섹션에서 쿼리 및 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
    
  2. 코드의 studentQuery3에 마우스 포인터를 놓아 할당된 형식이 IEnumerable(Of String)인지 확인합니다.

  3. Ctrl+F5를 눌러 애플리케이션을 빌드하고 실행합니다. 콘솔 창의 결과를 확인합니다.

Select 절에서 익명 형식을 만들려면

  1. 이 섹션의 코드를 추가하여 익명 형식이 쿼리에서 사용되는 방식을 확인합니다. 전체 레코드(이전 예제의 레코드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
    
  2. 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 공급자에 대한 설명서 및 샘플을 읽을 준비가 됩니다.

참고 항목