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


Знакомство с 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, поставщик 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 [LINQ to SQL]. Дополнительные сведения о реляционном конструкторе объектов см. в разделе Реляционный конструктор объектов.

Запросы из 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``1 для объединения результатов двух запросов в один. Он использует метод ToList``1 для возвращения результата запроса в виде универсального списка.

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 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)

Пошаговое руководство. Создание классов LINQ to SQL (реляционный конструктор объектов)

Как назначить хранимые процедуры для выполнения обновлений, вставок и удалений (реляционный конструктор объектов)

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

Chapter 17: LINQ в Programming Visual Basic 2008

См. также

Задачи

Примеры LINQ

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

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

Общие сведения о LINQ to DataSet

Методы DataContext (реляционный конструктор объектов)

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

LINQ

LINQ to SQL [LINQ to SQL]

Реляционный конструктор объектов