다음을 통해 공유


쿼리 작업의 형식 관계(Visual Basic)

LINQ(Language-Integrated Query) 쿼리 작업에 사용되는 변수는 강력한 형식이며 서로 호환되어야 합니다. 강력한 입력은 데이터 원본, 쿼리 자체 및 쿼리 실행에 사용됩니다. 다음 그림에서는 LINQ 쿼리를 설명하는 데 사용되는 용어를 식별합니다. 쿼리 부분에 대한 자세한 내용은 기본 쿼리 작업(Visual Basic)을 참조하세요.

요소가 강조 표시된 의사 코드 쿼리를 보여 주는 스크린샷

쿼리의 범위 변수 형식은 데이터 원본의 요소 형식과 호환되어야 합니다. 쿼리 변수의 형식은 절에 Select 정의된 시퀀스 요소와 호환되어야 합니다. 마지막으로, 시퀀스 요소의 형식은 쿼리를 실행하는 문에 For Each 사용되는 루프 제어 변수의 형식과도 호환되어야 합니다. 이 강력한 입력은 컴파일 시간에 형식 오류를 쉽게 식별할 수 있도록 합니다.

Visual Basic은 암시적 입력이라고도 하는 로컬 형식 유추를 구현하여 강력한 입력을 편리하게 만듭니다. 이 기능은 이전 예제에서 사용되며 LINQ 샘플 및 설명서 전체에서 사용되는 것을 볼 수 있습니다. Visual Basic에서 로컬 형식 유추는 Dim 문을 As 절 없이 사용하여 수행됩니다. 다음 예제에서는 city가 문자열로 강력하게 타입이 지정됩니다.

Dim city = "Seattle"

비고

로컬 형식 유추는 Option InferOn로 설정된 경우에만 작동합니다. 자세한 내용은 Option Infer 문을 참조하세요.

그러나 쿼리에서 로컬 형식 유추를 사용하는 경우에도 데이터 원본의 변수, 쿼리 변수 및 쿼리 실행 루프에 동일한 형식 관계가 있습니다. LINQ 쿼리를 작성하거나 설명서의 샘플 및 코드 예제를 사용할 때 이러한 형식 관계를 기본적으로 이해하는 것이 유용합니다.

데이터 원본에서 반환된 형식과 일치하지 않는 범위 변수에 대해 명시적 형식을 지정해야 할 수 있습니다. 절을 사용하여 범위 변수의 형식을 As 지정할 수 있습니다. 그러나 변환이 축소 변환 이고 Option Strict 로 설정된 경우 오류가 발생합니다 On. 따라서 데이터 원본에서 검색된 값에 대한 변환을 수행하는 것이 좋습니다. 메서드를 사용하여 데이터 원본에서 명시적 범위 변수 형식으로 값을 변환할 Cast 수 있습니다. 절에서 Select 선택한 값을 범위 변수의 형식과 다른 명시적 형식으로 캐스팅할 수도 있습니다. 이러한 점은 다음 코드에 설명되어 있습니다.

Dim numbers1() As Integer = {1, 2, 4, 16, 32, 64}
Dim numbers2() As Double = {5.0#, 10.0#, 15.0#}

' This code does not result in an error.
Dim numberQuery1 = From n As Integer In numbers1 Where n > 5

' This code results in an error with Option Strict set to On. The type Double
' cannot be implicitly cast as type Integer.
Dim numberQuery2 = From n As Integer In numbers2 Where n > 5

' This code casts the values in the data source to type Integer. The type of
' the range variable is Integer.
Dim numberQuery3 = From n In numbers2.Cast(Of Integer)() Where n > 5

' This code returns the value of the range variable converted to Integer. The type of
' the range variable is Double.
Dim numberQuery4 = From n In numbers2 Where n > 5 Select CInt(n)

원본 데이터의 전체 요소를 반환하는 쿼리

다음 예제에서는 원본 데이터에서 선택한 요소의 시퀀스를 반환하는 LINQ 쿼리 작업을 보여 있습니다. 소스 names는 문자열 배열을 포함하고 쿼리 출력은 문자 M으로 시작하는 문자열을 포함하는 시퀀스입니다.

Dim names = {"John", "Rick", "Maggie", "Mary"}
Dim mNames = From name In names
             Where name.IndexOf("M") = 0
             Select name

For Each nm In mNames
    Console.WriteLine(nm)
Next

이는 다음 코드와 동일하지만 훨씬 짧고 쓰기가 더 쉽습니다. 쿼리의 로컬 형식 유추에 의존하는 것이 Visual Basic의 기본 스타일입니다.

Dim names2 = {"John", "Rick", "Maggie", "Mary"}
Dim mNames2 As IEnumerable(Of String) =
    From name As String In names
    Where name.IndexOf("M") = 0
    Select name

For Each nm As String In mNames
    Console.WriteLine(nm)
Next

다음 관계는 형식이 암시적으로 또는 명시적으로 결정되는지 여부에 관계없이 이전 코드 예제 둘 다에 존재합니다.

  1. 데이터 원본 names에 있는 요소의 형식은 쿼리에서 범위 변수 name의 형식입니다.

  2. 선택한 개체의 형식으로, name쿼리 변수 mNames의 형식을 결정합니다. 다음은 name 문자열이므로 쿼리 변수는 Visual Basic에서 IEnumerable(Of String)입니다.

  3. mNames에서 정의된 쿼리가 For Each 루프에서 실행됩니다. 이 루프는 쿼리 실행 결과를 반복합니다. mNames실행될 때 문자열 시퀀스를 반환하므로 루프 반복 변수nm도 문자열입니다.

선택한 요소에서 하나의 필드를 반환하는 쿼리

다음 예제에서는 데이터 원본에서 선택한 각 요소의 한 부분만 포함하는 시퀀스를 반환하는 LINQ to SQL 쿼리 작업을 보여줍니다. 쿼리는 개체 컬렉션을 Customer 데이터 원본으로 사용하고 결과의 속성만 Name 프로젝션합니다. 고객 이름은 문자열이므로 쿼리는 문자열 시퀀스를 출력으로 생성합니다.

' Method GetTable returns a table of Customer objects.
Dim customers = db.GetTable(Of Customer)()
Dim custNames = From cust In customers
                Where cust.City = "London"
                Select cust.Name

For Each custName In custNames
    Console.WriteLine(custName)
Next

변수 간의 관계는 간단한 예제의 관계와 같습니다.

  1. 데이터 원본 customers에 있는 요소의 형식은 쿼리에서 범위 변수 cust의 형식입니다. 이 예제에서 해당 형식은 .입니다 Customer.

  2. 문장은 각 Select 개체의 Name 속성을 Customer 전체 개체 대신 반환합니다. 문자열이므로 Name 쿼리 변수 custNames는 다시 IEnumerable(Of String)이 되며, Customer가 아닙니다.

  3. 문자열 시퀀스를 custNames 나타내므로 For Each 루프의 반복 변수custName는 문자열이어야 합니다.

로컬 형식 유추가 없으면 다음 예제와 같이 이전 예제를 작성하고 이해하기가 더 번거로울 수 있습니다.

' Method GetTable returns a table of Customer objects.
 Dim customers As Table(Of Customer) = db.GetTable(Of Customer)()
 Dim custNames As IEnumerable(Of String) =
     From cust As Customer In customers
     Where cust.City = "London"
     Select cust.Name

 For Each custName As String In custNames
     Console.WriteLine(custName)
 Next

익명 형식이 필요한 쿼리

다음 예제에서는 더 복잡한 상황을 보여 있습니다. 이전 예제에서는 모든 변수의 형식을 명시적으로 지정하는 것이 불편했습니다. 이 예제에서는 불가능합니다. 이 쿼리의 절은 데이터 원본에서 전체 Customer 요소 또는 각 요소 Select 의 단일 필드를 선택하는 대신 원래 Customer 개체 Name 의 두 속성을 반환합니다 City. 절에 Select 대한 응답으로 컴파일러는 이러한 두 속성을 포함하는 익명 형식을 정의합니다. 루프에서 nameCityQuery를 반복하여 For Each을(를) 실행한 결과는 새 익명 형식의 인스턴스들로 이루어진 컬렉션입니다. 익명 형식에는 사용할 수 있는 이름이 없으므로 형식을 nameCityQuery 지정하거나 custInfo 명시적으로 지정할 수 없습니다. 즉, 익명 형식을 사용하면 대신 사용할 StringIEnumerable(Of String)형식 이름이 없습니다. 자세한 내용은 익명 형식을 참조하세요.

' Method GetTable returns a table of Customer objects.
Dim customers = db.GetTable(Of Customer)()
Dim nameCityQuery = From cust In customers
                    Where cust.City = "London"
                    Select cust.Name, cust.City

For Each custInfo In nameCityQuery
    Console.WriteLine(custInfo.Name)
Next

이전 예제의 모든 변수에 대한 형식을 지정할 수는 없지만 관계는 동일하게 유지됩니다.

  1. 데이터 원본에 있는 요소의 형식은 다시 쿼리의 범위 변수 형식입니다. 이 예제에서는 cust .의 Customer인스턴스입니다.

  2. 문은 Select 익명 형식을 생성하므로 쿼리 변수 nameCityQuery는 익명 형식으로 암시적으로 입력되어야 합니다. 익명 형식에는 사용할 수 있는 이름이 없으므로 명시적으로 지정할 수 없습니다.

  3. 루프의 반복 변수 For Each 형식은 2단계에서 만든 익명 형식입니다. 형식에 사용할 수 있는 이름이 없으므로 루프 반복 변수의 형식을 암시적으로 결정해야 합니다.

참고하십시오