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

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

LINQ позволяет запрашивать данные из базы данных SQL Server, XML, массивов и коллекций в памяти, наборов данных ADO.NET или любого другого локального или удаленного источника данных, который поддерживает LINQ.Все это можно делать с помощью обычных элементов языка Visual Basic.Поскольку запросы пишутся на языке Visual Basic, результаты запроса возвращаются в виде строго типизированных объектов.Эти объекты поддерживают технологию IntelliSense, что позволяет писать код быстрее и перехватывать ошибки в запросах при компиляции, а не при выполнении.Запросы LINQ можно использовать в качестве источника дополнительных запросов для уточнения результатов.Они также могут быть связаны с элементами управления, чтобы пользователи легко могли просматривать и изменять результаты запроса.

Например, в следующем примере кода показан запрос LINQ, возвращающий список заказчиков из коллекции, и группирующий их по расположению.

' Obtain a list of customers.
Dim customers As List(Of Customer) = GetCustomers()

' Return customers that are grouped based on country.
Dim countries = From cust In customers
                Order By cust.Country, cust.City
                Group By CountryName = cust.Country
                Into CustomersInCountry = Group, Count()
                Order By CountryName

' Output the results.
For Each country In countries
    Debug.WriteLine(country.CountryName & " count=" & country.Count)

    For Each customer In country.CustomersInCountry
        Debug.WriteLine("   " & customer.CompanyName & "  " & customer.City)
    Next
Next

' Output:
'   Canada count=2
'      Contoso, Ltd  Halifax
'      Fabrikam, Inc.  Vancouver
'   United States count=1
'      Margie's Travel  Redmond

В этом разделе содержатся сведения о следующих областях:

  • Запуск примеров

  • Поставщики LINQ

  • Структура запроса LINQ

  • Операторы запросов LINQ в Visual Basic

  • Подключение к базе данных с помощью LINQ to SQL

  • Возможности Visual Basic, поддерживающего LINQ

  • Отложенное и немедленное выполнение запроса

  • XML в Visual Basic

  • Связанные ресурсы

  • Практические и пошаговые руководства

Запуск примеров

Для выполнения примеров во введении и в разделе "структура" запроса LINQ, включает следующий код, который возвращает список клиентов и заказов.

' Return a list of customers.
Private Function GetCustomers() As List(Of Customer)
    Return New List(Of Customer) From
        {
            New Customer With {.CustomerID = 1, .CompanyName = "Contoso, Ltd", .City = "Halifax", .Country = "Canada"},
            New Customer With {.CustomerID = 2, .CompanyName = "Margie's Travel", .City = "Redmond", .Country = "United States"},
            New Customer With {.CustomerID = 3, .CompanyName = "Fabrikam, Inc.", .City = "Vancouver", .Country = "Canada"}
        }
End Function

' Return a list of orders.
Private Function GetOrders() As List(Of Order)
    Return New List(Of Order) From
        {
            New Order With {.CustomerID = 1, .Amount = "200.00"},
            New Order With {.CustomerID = 3, .Amount = "600.00"},
            New Order With {.CustomerID = 1, .Amount = "300.00"},
            New Order With {.CustomerID = 2, .Amount = "100.00"},
            New Order With {.CustomerID = 3, .Amount = "800.00"}
        }
End Function

' Customer Class.
Private Class Customer
    Public Property CustomerID As Integer
    Public Property CompanyName As String
    Public Property City As String
    Public Property Country As String
End Class

' Order Class.
Private Class Order
    Public Property CustomerID As Integer
    Public Property Amount As Decimal
End Class

Поставщики LINQ

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

Visual Basic содержит следующие поставщики LINQ.

Поставщик

Описание

LINQ to Objects

Поставщик LINQ to Objects позволяет делать запросы к коллекциям и массивам, находящимся в памяти.Если объект поддерживает интерфейс IEnumerable или IEnumerable<T>, поставщик LINQ to Objects позволяет делать к объекту запросы.

Можно включить поставщик LINQ to Objects путем импорта пространства имен System.Linq, которое импортируется по умолчанию для всех проектов Visual Basic.

Дополнительные сведения о поставщике LINQ to Objects см. в разделе LINQ to Objects.

Запросы из LINQ в SQL

Поставщик LINQ to SQL позволяет запрашивать и изменять данные в базе данных SQL Server.Это упрощает сопоставление объектной модели приложения и таблиц и объектов в базе данных.

Visual Basic упрощает работу с LINQ to SQL включением реляционного конструктора объектов (O/R-конструктора).Этот конструктор используется для создания объектной модели в приложении, которое сопоставляет на объекты в базе данных. Реляционный конструктор объектов также предоставляет функцию хранимые процедуры и функции сопоставления в объект DataContext, управляющий взаимодействие с базой данных и сохраняет состояние для проверки оптимистического параллелизма.

Дополнительные сведения о поставщике LINQ to SQL см. в разделе LINQ to SQL.Дополнительные сведения о реляционном конструкторе объектов см. в разделе Object Relational Designer (O/R Designer).

Запросы из LINQ в XML

Поставщик LINQ to XML позволяет запрашивать и изменять XML.Можно изменить XML в памяти, загрузить его из файла, сохранить в файл.

Кроме того, поставщик LINQ to XML разрешает использование литералов XML и свойств оси XML, что позволяет писать XML непосредственно в коде Visual Basic.Дополнительные сведения см. в разделе XML в Visual Basic.

LINQ to DataSet

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

Дополнительные сведения см. в разделе LINQ to DataSet.

Структура запроса LINQ

Запрос LINQ, часто называемый как выражение запроса, состоит из комбинации предложений запросов, определяющих источники данных и переменные итерации для запроса.Выражение запроса может также включать инструкции сортировки, фильтрации, группировки и соединения, а также вычисления, применимые к источнику данных.Синтаксис выражения запроса напоминает синтаксис SQL; поэтому большая часть синтаксиса может показаться знакомой.

Выражение запроса начинается с предложения From.Это предложение указывает исходные данные для запроса и переменные, которые используются для обращения к каждому элементу источника данных по отдельности.Эти переменные называются переменные диапазона или итерационные переменные.Предложение From является обязательным для запроса, за исключением запросов Aggregate, в которых предложение From необязательно.После определения области и источника запроса в предложении From или Aggregate можно использовать любую комбинацию предложений запроса для его уточнения.Подробные сведения о предложениях запросов можно найти в теме "Операторы Visual Basic запросов LINQ" далее в этом разделе.Например, следующий запрос определяет исходную коллекцию данных клиента как переменную customers и как итерационная переменная cust.

Dim customers = GetCustomers()

Dim queryResults = From cust In customers

For Each result In queryResults
    Debug.WriteLine(result.CompanyName & "  " & result.Country)
Next

' Output:
'   Contoso, Ltd  Canada
'   Margie's Travel  United States
'   Fabrikam, Inc.  Canada

Данный пример сам по себе является допустимым запросом; однако запрос становится гораздо более мощным при добавлении нескольких предложений для уточнения результата.Например, можно добавить предложение Where для фильтрации результата по одному или нескольким значениям.Выражения запроса — это одна строка кода; можно просто добавлять дополнительные предложения в конец запроса.Можно разбить запрос на несколько строк текста для улучшения читаемости с помощью знака продолжения строки (_).В следующем примере кода показан пример запроса с предложением Where.

Dim queryResults = From cust In customers
                   Where cust.Country = "Canada"

Другое мощное предложение запроса — предложение Select. Оно позволяет возвращать только выбранные поля из источника данных.Запросы LINQ возвращают перечислимые коллекции строго типизированных объектов.Запрос может вернуть коллекцию как анонимных, так и именованных типов.Можно использовать предложение Select для получения только одного поля из источника данных.При этом тип возвращаемой коллекции — это тип этого поля.Можно также использовать предложение Select для получения нескольких полей из источника данных.При этом тип возвращаемой коллекции — это новый анонимный тип.Можно также сопоставить возвращенные запросом поля с полями указанного именованного типа.В следующем примере кода показано выражение запроса, возвращающее коллекцию анонимных типов, члены которых заполняются данными из выбранных полей источника данных.

Dim queryResults = From cust In customers
               Where cust.Country = "Canada"
               Select cust.CompanyName, cust.Country

Запросы LINQ могут также использоваться для объединения нескольких источников данных и получения единого результата.Это можно сделать с помощью одного или нескольких предложений From или с помощью предложений Join или Group Join.В следующем примере кода показано выражение запроса, объединяющее данные клиентов и заказов и возвращающее коллекцию анонимных типов, содержащих их данные.

Dim customers = GetCustomers()
Dim orders = GetOrders()

Dim queryResults = From cust In customers, ord In orders
           Where cust.CustomerID = ord.CustomerID
           Select cust, ord

For Each result In queryResults
    Debug.WriteLine(result.ord.Amount & "  " & result.ord.CustomerID & "  " & result.cust.CompanyName)
Next

' Output:
'   200.00  1  Contoso, Ltd
'   300.00  1  Contoso, Ltd
'   100.00  2  Margie's Travel
'   600.00  3  Fabrikam, Inc.
'   800.00  3  Fabrikam, Inc.

Можно использовать предложение Group Join для получения иерархического результата запроса, содержащего коллекцию объектов клиента.Каждый объект клиента имеет свойство, содержащее коллекцию всех заказов этого клиента.В следующем примере показано выражение запроса, объединяющее данные клиентов и заказов как иерархический результат и возвращающее коллекцию анонимных типов.Запрос возвращает тип, у которого есть свойство CustomerOrders, содержащее коллекцию данных заказов клиента.У него также есть свойство OrderTotal, которое содержит общую сумму всех заказов этого клиента.(Этот запрос эквивалентен LEFT OUTER JOIN.)

Dim customers = GetCustomers()
Dim orders = GetOrders()

Dim queryResults = From cust In customers
                   Group Join ord In orders On
                     cust.CustomerID Equals ord.CustomerID
                     Into CustomerOrders = Group,
                          OrderTotal = Sum(ord.Amount)
                   Select cust.CompanyName, cust.CustomerID,
                          CustomerOrders, OrderTotal

For Each result In queryResults
    Debug.WriteLine(result.OrderTotal & "  " & result.CustomerID & "  " & result.CompanyName)
    For Each ordResult In result.CustomerOrders
        Debug.WriteLine("   " & ordResult.Amount)
    Next
Next

' Output:
'   500.00  1  Contoso, Ltd
'      200.00
'      300.00
'   100.00  2  Margie's Travel
'      100.00
'   1400.00  3  Fabrikam, Inc.
'      600.00
'      800.00

Имеется несколько дополнительных операторов запросов LINQ, которые можно использовать для создания мощных выражений запросов.В следующей теме этого раздела описываются различные предложения запросов, которые можно использовать в выражениях запросов.Дополнительные сведения о предложениях запросов в Visual Basic см. в Запросы (Visual Basic).

Операторы запросов LINQ в Visual Basic

Классы в поддерживающих запросы LINQ пространствах имен (в частности, System.Linq) содержат методы создания и уточнения запросов. Их можно использовать исходя из нужд приложения.Visual Basic содержит ключевые слова для наиболее общих предложений запросов, как описано в следующей таблице.

Термин

Определение

Предложение From (Visual Basic)

Предложение From или Aggregate требуется для начала запроса.Предложение From определяет коллекцию источника и переменную итерации для запроса.Например:

Предложение Select (Visual Basic)

Необязательный параметр.Объявляет набор переменных итераций для запроса.Например:

Если не указано предложение Select, то переменные итераций для запроса — это переменные итераций, указанные в предложении From или Aggregate.

Предложение Where (Visual Basic)

Необязательный параметр.Устанавливает условия фильтрации для запроса.Например:

Предложение Order By (Visual Basic)

Необязательный параметр.Задает порядок сортировки столбцов в запросе.Например:

Предложение Join (Visual Basic)

Необязательный параметр.Объединяет две коллекции в одну.Например:

Предложение Group By (Visual Basic)

Необязательный параметр.Группирует элементы результата запроса.Может использоваться для применения агрегатных функций к каждой группе.Например:

Предложение Group Join (Visual Basic)

Необязательный параметр.Объединяет две коллекции в одну иерархическую.Например:

Предложение Aggregate (Visual Basic)

Предложение From или Aggregate требуется для начала запроса.Предложение Aggregate применяет одну или несколько агрегатных функций к коллекции.Например, можно использовать предложение Aggregate для вычисления суммы всех возвращенных запросом элементов.

Предложение Aggregate можно также использовать для изменения запроса.Например, можно использовать предложение Aggregate для выполнения вычислений с результатом связанного запроса.

Предложение Let (Visual Basic)

Необязательный параметр.Вычисляет значение и присваивает его новой переменной в запросе.Например:

Предложение Distinct (Visual Basic)

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

Предложение Skip (Visual Basic)

Необязательный параметр.Пропускает заданное число элементов в коллекции и возвращает остальные элементы.Например:

Предложение Skip While (Visual Basic)

Необязательный параметр.Пропускает элементы в коллекции, пока заданное условие является true и затем возвращает оставшиеся элементы.Например:

Предложение Take (Visual Basic)

Необязательный параметр.Возвращает указанное число последовательных элементов от начала коллекции.Например:

Предложение Take While (Visual Basic)

Необязательный параметр.Включает элементы в коллекцию, пока заданное условие является true, и затем пропускает оставшиеся элементы.Например:

Дополнительные сведения о предложениях запросов в Visual Basic см. в Запросы (Visual Basic).

Можно использовать дополнительные возможности запросов LINQ путем обращения к членам перечислимых и доступных для запроса типов, предоставляемых LINQ.Можно использовать эти дополнительные возможности, вызвав конкретный оператор запроса на результате выражения запроса.Например, код следующего примера использует метод Union для объединения результатов двух запросов в один.Он использует метод ToList<TSource> для возвращения результата запроса в виде универсального списка.

Public Function GetAllCustomers() As List(Of Customer)
    Dim customers1 = From cust In domesticCustomers
    Dim customers2 = From cust In internationalCustomers

    Dim customerList = customers1.Union(customers2)

    Return customerList.ToList()
End Function

Сведения о дополнительных возможностях LINQ см. в Общие сведения о стандартных операторах запроса.

Подключение к базе данных с помощью LINQ to SQL

В Visual Basic идентификация объектов базы данных SQL Server (таблицы, представления, хранимые процедуры), к которым нужен доступ, происходит с помощью файла LINQ to SQL.Файл LINQ to SQL имеет расширение .dbml.

При наличии допустимого подключения к базе данных SQL Server можно добавить в проект шаблон элемента Классы LINQ to SQL.Это даст возможность отобразить реляционный конструктор объектов (O/R-конструктор).O/R-конструктор дает возможность перетаскивать элементы, к которым нужен доступ в коде, из обозревателя серверов / обозревателя баз данных на поверхность конструктора.Файл LINQ to SQL добавляет объект DataContext в проект.Этот объект включает в себя свойства и коллекции для таблиц и представлений, к которым нужен доступ, а также необходимые методы для хранимых процедур.После сохранения изменений в файле LINQ to SQL (.dbml) можно получить доступ к этим объектам в коде, обратившись к определенному O/R-конструктором объекту DataContext.Объекту DataContext для проекта присваивается имя на основе имени файла LINQ to SQL.Например, файл LINQ to SQL с именем Northwind.dbml создаст объект DataContext с именем NorthwindDataContext.

Примеры с пошаговыми инструкциями см. в разделах Практическое руководство. Выполнение запросов к базе данных с помощью LINQ (Visual Basic) и Практическое руководство. Вызов хранимой процедуры с помощью LINQ (Visual Basic).

Возможности Visual Basic, поддерживающего LINQ

Visual Basic имеет другие важные возможности, упрощающие использование LINQ и уменьшающие требуемый для написания запросов объем кода.Ниже перечислены некоторые из этих методов.

  • Анонимные типы, позволяющие создать новый тип, основанный на результатах запроса.

  • Неявно типизированные переменные, позволяющие отложить указание типа и позволить компилятору передавать тип, основанный на результатах запроса.

  • Методы расширения, позволяющие расширять существующий тип своими собственными методами без изменения самого типа.

Дополнительные сведения см. в разделе Возможности Visual Basic, поддерживающие LINQ.

Отложенное и немедленное выполнение запроса

Выполнение запроса разделено с его созданием.После создания запроса его выполнение инициируется отдельным механизмом.Запрос может выполняться по мере его определения (немедленное выполнение), или его определение может быть сохранено и запрос может быть выполнен позднее (отложенное выполнение).

По умолчанию при создании запроса он не выполняется.Вместо этого определение запроса хранится в переменной, используемой для ссылки на результаты запроса.Если доступ к переменной результата запроса выполняется позже в коде, например в цикле For…Next, запрос выполняется.Такой процесс называется отложенным выполнением.

Запросы могут также выполняться при их определении. Это называется немедленное выполнение.Можно инициировать немедленное выполнение, применив метод, требующий доступа к отдельным элементам результата запроса.Это может быть результатом использования агрегатных функций, таких как Count, Sum, Average, Min или Max.Дополнительные сведения об агрегатных функциях см. в разделе Предложение Aggregate (Visual Basic).

Использование методов ToList или ToArray также приведет к немедленному выполнению.Это может быть полезно, если надо выполнить запрос немедленно и занести результаты в кэш.Дополнительные сведения об этих методах см. в разделе Преобразование типов данных.

Дополнительные сведения о выполнении запроса см. в разделе Написание первого запроса LINQ (Visual Basic).

XML в Visual Basic

Возможности XML в Visual Basic включают литералы XML и свойства оси XML, что позволяет легко создавать, запрашивать, изменять и получать доступ к XML в коде.Литералы XML позволяют писать XML непосредственно в коде.Компилятор Visual Basic обрабатывает XML как объект данных первого класса.

В следующем примере показано, как создать элемент XML, получить доступ к его дочерним элементам и атрибутам и делать запросы к содержимому элемента с помощью LINQ.

' Place Imports statements at the top of your program.  
Imports <xmlns:ns="http://SomeNamespace">

Module Sample1

    Sub SampleTransform()

        ' Create test by using a global XML namespace prefix. 

        Dim contact = 
            <ns:contact>
                <ns:name>Patrick Hines</ns:name>
                <ns:phone ns:type="home">206-555-0144</ns:phone>
                <ns:phone ns:type="work">425-555-0145</ns:phone>
            </ns:contact>

        Dim phoneTypes = 
          <phoneTypes>
              <%= From phone In contact.<ns:phone> 
                  Select <type><%= phone.@ns:type %></type> 
              %>
          </phoneTypes>

        Console.WriteLine(phoneTypes)
    End Sub

End Module

Дополнительные сведения см. в разделе XML в Visual Basic.

Связанные ресурсы

Раздел

Описание

XML в Visual Basic

Описание возможностей XML в Visual Basic, к которым можно делать запросы и которые позволяют включать XML как объекты данных первого класса в коде Visual Basic.

Запросы (Visual Basic)

Содержит справочные сведения о предложениях запросов, которые доступны в Visual Basic.

LINQ

Содержит общие сведения, рекомендации по программированию и примеры для LINQ.

LINQ to SQL

Содержит общие сведения, рекомендации по программированию и примеры для LINQ to SQL.

LINQ to Objects

Содержит общие сведения, рекомендации по программированию и примеры для LINQ to Objects.

LINQ to ADO.NET (Страница портала)

Содержит ссылки на общие сведения, рекомендации по программированию и примеры для LINQ ADO.NET.

LINQ to XML

Содержит общие сведения, рекомендации по программированию и примеры для LINQ to XML.

Практические и пошаговые руководства

Практическое руководство. Выполнение запросов к базе данных с помощью LINQ (Visual Basic)

Практическое руководство. Вызов хранимой процедуры с помощью LINQ (Visual Basic)

Практическое руководство. Изменение данных в базе данных с помощью LINQ (Visual Basic)

Практическое руководство. Объединение данных с помощью LINQ с использованием соединений (Visual Basic)

Практическое руководство. Сортировка результатов запроса с помощью LINQ (Visual Basic)

Практическое руководство. Фильтрование результатов запроса с помощью LINQ (Visual Basic)

Практическое руководство. Выполнение над данными функций Count, Sum и Average с помощью LINQ (Visual Basic)

Практическое руководство. Поиск минимального или максимального значения в результатах запроса с помощью LINQ (Visual Basic)

Walkthrough: Creating LINQ to SQL Classes (O/R Designer)

How to: Assign Stored Procedures to Perform Updates, Inserts, and Deletes (O/R Designer)

Главы в популярных книгах

Chapter 17: LINQ в книге Programming Visual Basic 2008

См. также

Задачи

Примеры LINQ

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

Общие сведения о LINQ to XML в Visual Basic

LINQ to DataSet Overview

DataContext Methods (O/R Designer)

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

LINQ

LINQ to SQL

Object Relational Designer (O/R Designer)