Знакомство с LINQ в Visual Basic
Language-Integrated Query (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 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 в 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
можно добавить любую комбинацию предложений для уточнения запроса. Дополнительные сведения о предложениях запросов см. в разделе Операторы запросов LINQ Visual Basic далее в этом разделе. Например, следующий запрос определяет исходную коллекцию данных клиента как переменную 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 см. в разделе Запросы.
Операторы запросов LINQ Visual Basic
Классы в пространствах имен 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". Это позволит отобразить реляционный конструктор объектов (O/R-конструктор). Конструктор O/R позволяет перетаскивать элементы, к которым вы хотите получить доступ в коде, из Обозреватель Server Обозреватель/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
См. также раздел
- Встроенный язык запросов LINQ
- Overview of LINQ to XML in Visual Basic (Общие сведения о LINQ to XML в Visual Basic)
- Общие сведения о LINQ to DataSet
- LINQ to SQL
- Средства LINQ to SQL в Visual Studio
- Методы DataContext (реляционный конструктор объектов)