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


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

Language-Integrated Запрос (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 ", добавьте следующий код, который возвращает списки клиентов и заказов.

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

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

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

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

Дополнительные сведения о поставщике LINQ to SQL см. в разделе LINQ to SQL. Дополнительные сведения об реляционном конструкторе объектов см. в статье LINQ to SQL Tools в Visual Studio.
LINQ to XML Поставщик LINQ to XML позволяет запрашивать и изменять XML. Можно изменять XML в памяти или загружать и сохранять XML в файле.

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

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

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

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

Выражение запроса начинается с From предложения. Это предложение определяет исходные данные для запроса и переменные, используемые для ссылки на каждый элемент исходных данных по отдельности. Эти переменные называются переменными диапазона или переменными итерации. Предложение From обязательно для запроса, за исключением запросов Aggregate, где предложение From является необязательным. После определения области и источника запроса в клаузах From или Aggregate можно включить любое сочетание клауз запроса для уточнения запроса. Дополнительные сведения о предложениях запросов см. в разделе Visual Basic LINQ Query Operators в этом разделе ниже. Например, следующий запрос определяет исходную коллекцию данных о клиентах как переменную 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 свойство, которое включает общую сумму всех заказов этого клиента. (Этот запрос эквивалентен левому внешнему соединению.)

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

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

Предложение From

Для начала запроса требуется либо From предложение, либо Aggregate предложение. Предложение From указывает исходную коллекцию и переменную итерации для запроса. Рассмотрим пример.

' Returns the company name for all customers for which
' the Country is equal to "Canada".
Dim names = From cust In customers
            Where cust.Country = "Canada"
            Select cust.CompanyName

Предложение Select

Необязательно. УсловиеSelect объявляет набор переменных итерации для выполнения запроса. Рассмотрим пример.

' Returns the company name and ID value for each
' customer as a collection of a new anonymous type.
Dim customerList = From cust In customers
                   Select cust.CompanyName, cust.CustomerID

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

Предложение Where

Необязательно. Предложение Where указывает условие фильтрации для запроса. Рассмотрим пример.

' Returns all product names for which the Category of
' the product is "Beverages".
Dim names = From product In products
            Where product.Category = "Beverages"
            Select product.Name

Оператор "Order By"

Необязательно. Предложение Order By указывает порядок сортировки столбцов в запросе. Рассмотрим пример.

' Returns a list of books sorted by price in 
' ascending order.
Dim titlesAscendingPrice = From b In books
                           Order By b.price

Предложение Join

Необязательно. Join Выражение объединяет две коллекции в одну коллекцию. Рассмотрим пример.

' Returns a combined collection of all of the 
' processes currently running and a descriptive
' name for the process taken from a list of 
' descriptive names.
Dim processes = From proc In Process.GetProcesses
                Join desc In processDescriptions
                  On proc.ProcessName Equals desc.ProcessName
                Select proc.ProcessName, proc.Id, desc.Description

Группировка данных с использованием Group By

Необязательно. Предложение Group By группит элементы результата запроса. Его можно использовать для применения агрегатных функций к каждой группе. Рассмотрим пример.

' Returns a list of orders grouped by the order date
' and sorted in ascending order by the order date.
Dim orderList = From order In orders
                Order By order.OrderDate
                Group By OrderDate = order.OrderDate
                Into OrdersByDate = Group

Предложение "Присоединение к группе"

Необязательно. КлаузаGroup Join объединяет две коллекции в одну иерархическую коллекцию. Рассмотрим пример.

' Returns a combined collection of customers and
' customer orders.
Dim customerList = From cust In customers
                   Group Join ord In orders On
                     cust.CustomerID Equals ord.CustomerID
                   Into CustomerOrders = Group,
                        TotalOfOrders = Sum(ord.Amount)
                   Select cust.CompanyName, cust.CustomerID,
                          CustomerOrders, TotalOfOrders

клаузула агрегации

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

' Returns the sum of all order amounts.
Dim orderTotal = Aggregate order In orders
                 Into Sum(order.Amount)

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

' Returns the customer company name and largest 
' order amount for each customer.
Dim customerMax = From cust In customers
                  Aggregate order In cust.Orders
                  Into MaxOrder = Max(order.Amount)
                  Select cust.CompanyName, MaxOrder

Конструкция Let

Необязательно. ПредложениеLet вычисляет значение и назначает его новой переменной в запросе. Рассмотрим пример.

' Returns a list of products with a calculation of
' a ten percent discount.
Dim discountedProducts = From prod In products
                         Let Discount = prod.UnitPrice * 0.1
                         Where Discount >= 50
                         Select prod.Name, prod.UnitPrice, Discount

Отдельный пункт

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

' Returns a list of cities with no duplicate entries.
Dim cities = From item In customers
             Select item.City
             Distinct

Пропустить пункт

Необязательно. ПредложениеSkip проходит указанное число элементов в коллекции, а затем возвращает оставшиеся элементы. Рассмотрим пример.

' Returns a list of customers. The first 10 customers
' are ignored and the remaining customers are
' returned.
Dim customerList = From cust In customers
                   Skip 10

Пропустить предложение "Пока"

Необязательно. Условие Skip While обходит элементы коллекции до тех пор, пока выполняется указанное условие true, а затем возвращает остальные элементы. Рассмотрим пример.

' Returns a list of customers. The query ignores all
' customers until the first customer for whom
' IsSubscriber returns false. That customer and all
' remaining customers are returned.
Dim customerList = From cust In customers
                   Skip While IsSubscriber(cust)

Статья Take

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

' Returns the first 10 customers.
Dim customerList = From cust In customers
                   Take 10

Предложение Take While

Необязательно. Предложение Take While включает элементы в коллекцию до тех пор, пока указано условие true, после чего оставшиеся элементы игнорируются. Рассмотрим пример.

' Returns a list of customers. The query returns
' customers until the first customer for whom 
' HasOrders returns false. That customer and all 
' remaining customers are ignored.
Dim customersWithOrders = From cust In customers
                          Order By cust.Orders.Count Descending
                          Take While HasOrders(cust)

Использование дополнительных функций запроса LINQ

Дополнительные функции запроса LINQ можно использовать, вызывая элементы перечисленных и запрашиваемых типов, предоставляемых LINQ. Эти дополнительные возможности можно использовать, вызвав конкретный оператор запроса для результата выражения запроса. Например, в следующем примере метод используется Enumerable.Union для объединения результатов двух запросов в один результат запроса. Он использует Enumerable.ToList метод для возврата результата запроса в виде универсального списка.

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

Примеры с пошаговыми инструкциями см. в статье "Практическое руководство. Запрос базы данных и практическое руководство. Вызов хранимой процедуры".

Функции Visual Basic, поддерживающие LINQ

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

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

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

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

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

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

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

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

Запросы могут выполняться сразу после их определения, что называется немедленным выполнением. Немедленное выполнение можно активировать, применяя метод, требующий доступа к отдельным элементам результата запроса. Это может быть результатом включения агрегатной функции, например Count, Sum, , AverageMinили Max. Дополнительные сведения об агрегатных функциях см. в разделе Aggregate Clause.

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

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

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.

Тема Описание
XML Описывает функции XML в Visual Basic, которые можно запрашивать и которые позволяют включать XML в качестве объектов данных первого класса в код Visual Basic.
Запросы Предоставляет справочные сведения о конструкции запросов, имеющихся в Visual Basic.
LINQ (запросLanguage-Integrated) Содержит общие сведения, рекомендации по программированию и примеры для LINQ.
LINQ to SQL Содержит общие сведения, рекомендации по программированию и примеры для LINQ to SQL.
LINQ к объектам Содержит общую информацию, рекомендации по программированию и примеры для LINQ to Objects.
LINQ to ADO.NET (страница портала) Содержит ссылки на общие сведения, рекомендации по программированию и примеры для LINQ to ADO.NET.
LINQ to XML Содержит общие сведения, рекомендации по программированию и примеры для LINQ to XML.

Инструкции и пошаговое руководство

Практическое руководство. Запрос базы данных

Практическое руководство. Вызов хранимой процедуры

Практическое руководство. Изменение данных в базе данных

Как объединить данные с помощью соединений

Практическое руководство. Сортировка результатов запроса

Практическое руководство. Фильтрация результатов запроса

Как: подсчитывать, суммировать или вычислять среднее значение данных

Практическое руководство. Поиск минимального или максимального значения в результатах запроса

Практическое руководство. Назначение хранимых процедур для выполнения обновлений, вставок и удалений (конструктор операций ввода-вывода)

Глава 17. LINQ в программировании Visual Basic 2008

См. также