Поделиться через


Отношения типов в операциях запроса (Visual Basic)

Обновлен: Ноябрь 2007

Переменные, используемые в операциях запроса LINQ (Language-Integrated Query), являются строго типизированными и должны быть совместимы друг с другом. Строгая типизация используется в источнике данных, в самом запросе и при выполнении запроса. На следующем рисунке показаны термины, используемые для описания запроса LINQ. Дополнительные сведения о частях запроса см. в разделе Основные операции запроса (Visual Basic).

Части запроса LINQ
Запрос символического кода с маркированными элементами.

Тип переменной диапазона в запросе должен быть совместим с типом элементов в источнике данных. Тип переменной запроса должен быть совместим с последовательностью элемента, определенной в предложении Select. И наконец, тип элементов последовательности также должен быть совместим с типом переменной цикла, которая используется в операторе For Each, выполняющем запрос. Строгая типизация упрощает идентификацию ошибок типов во время компиляции.

Visual Basic 2008 делает строгую типизацию удобной за счет реализации локального определения типа, также называемого неявной типизацией. Эта возможность используется в предыдущем примере, и применяется примерах и документации по LINQ. В Visual Basic локальное определение типа осуществляется при помощи оператора Dim без предложения As. В следующем примере city строго типизирован в качестве строки.

Dim city = "Seattle"
Bb384935.alert_note(ru-ru,VS.90).gifПримечание.

Локальное определение типа работает только тогда, когда Option Infer имеет значение On. Дополнительные сведения см. в разделе Оператор Option Infer.

Однако даже если локальное определение типа используется в запросе, отношение типов между переменными в источнике данных, переменной запрос и переменной цикла, выполняющего запрос, остается неизменным. При написании запросов LINQ или работе с примерами кода в документации знание отношений типов является полезным моментом.

Запросы, которые возвращают целые элементы из источника данных

В следующем примере показана операция запроса LINQ, возвращающая последовательность элементов, выбранных из источника данных. Источник names содержит массив строк, а результат запроса представляет собой последовательность, содержащую строки, которые начинаются с буквы М.

Dim names = New String() {"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() As String = {"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 является строкой, поэтому переменная запроса имеет тип IEnumerable(Of String) в Visual Basic.

  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 явным образом. Это значит, что при наличии анонимного типа отсутствует имя типа, которое можно использовать вместо String в IEnumerable(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. Так как тип не имеет имени, тип переменной итерации цикла должен быть определен неявным образом.

См. также

Основные понятия

Анонимные типы

Вывод локального типа

Знакомство с LINQ в Visual Basic

Другие ресурсы

Приступая к работе с LINQ в Visual Basic

LINQ в Visual Basic

Запросы (Visual Basic)