Знакомство с 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", добавьте следующий код, который возвращает списки клиентов и заказов.
' 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.
Provider | Description |
---|---|
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 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 можно изменить в памяти, загрузить из файла и сохранить в файл. Кроме того, поставщик 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
, которое содержит общую сумму всех заказов этого клиента. (Этот запрос эквивалентен 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
Классы в пространствах имен System.Linq и других пространствах имен, поддерживающих запросы LINQ (в частности, System.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 - предложение
Необязательно. Предложение 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 - предложение
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 - предложение
Необязательно. Предложение Distinct
ограничивает значения текущей переменной итерации, чтобы исключить повторяющиеся значения в результатах запроса. Например:
' Returns a list of cities with no duplicate entries.
Dim cities = From item In customers
Select item.City
Distinct
Skip - предложение
Необязательно. Предложение 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 - предложение
Необязательно. Предложение 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 . Это позволит отобразить реляционный конструктор объектов (O/R-конструктор). Конструктор O/R позволяет перетаскивать элементы, к которым вы хотите получить доступ в коде, с сервера Обозреватель Database Обозреватель/ на область конструктора. Файл LINQ to SQL добавляет в проект объект DataContext. Этот объект включает свойства и коллекции для таблиц и представлений, к которым нужно получить доступ, а также необходимые методы для хранимых процедур. После сохранения изменений в файле LINQ to SQL (DBML) можно получить доступ к этим объектам в коде, обратившись к определенному O/R-конструктором объекту DataContext. Объекту 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
, Average
, Min
или Max
. Дополнительные сведения об агрегатных функциях см. в предложении Агрегата.
Принудительно вызвать немедленное выполнение запросов позволяют также методы 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 | Содержит общие сведения, рекомендации по программированию и примеры для LINQ. |
LINQ to SQL | Содержит общие сведения, рекомендации по программированию и примеры для LINQ to SQL. |
LINQ to Objects | Содержит общие сведения, рекомендации по программированию и примеры для LINQ to Objects. |
LINQ to ADO.NET (Страница портала) | Содержит ссылки на общие сведения, рекомендации по программированию и примеры для LINQ to ADO.NET. |
LINQ to XML | Содержит общие сведения, рекомендации по программированию и примеры для LINQ to XML. |
Инструкции и пошаговое руководство
How to: Query a Database (Практическое руководство. Выполнение запросов к базе данных)
How to: Call a Stored Procedure (Практическое руководство. Вызов хранимой процедуры)
How to: Modify Data in a Database (Практическое руководство. Изменение данных в базе данных)
How to: Combine Data with Joins (Практическое руководство. Объединение данных с помощью соединений)
How to: Sort Query Results (Практическое руководство. Сортировка результатов запроса)
How to: Filter Query Results (Практическое руководство. Фильтрование результатов запроса)
How to: Count, Sum, or Average Data (Практическое руководство. Выполнение функций Count, Sum и Average)
How to: Find the Minimum or Maximum Value in a Query Result (Практическое руководство. Нахождение минимального или максимального значения в результатах запроса)
Избранные главы книги
Глава 17. LINQ в программировании Visual Basic 2008