This documentation is archived and is not being maintained.

Visual Basic Features That Support LINQ

Updated: September 2008

The name Language-Integrated Query (LINQ) refers to new technology in Visual Basic 2008 that supports query syntax and other new language constructs directly in the language. With LINQ, you do not have to learn a new language to query against an external data source. You can query against data in relational databases, XML stores, or objects by using Visual Basic. This integration of query capabilities into the language enables compile-time checking for syntax errors and type safety. This integration also ensures that you already know most of what you have to know to write rich, varied queries in Visual Basic 2008.

The following sections describe the new language constructs in enough detail to enable you to get started in reading the introductory documentation, code examples, and sample applications. You can also click the links to find more detailed explanations of how the language features come together to enable language-integrated query. A good place to start is Walkthrough: Writing Queries in Visual Basic.

Query expressions in Visual Basic 2008 can be expressed in a declarative syntax similar to that of SQL or XQuery. At compile time, query syntax is converted into method calls to a LINQ provider's implementation of the standard query operator extension methods. Applications control which standard query operators are in scope by specifying the appropriate namespace with an Imports statement. Syntax for a Visual Basic query expression looks like this:

Dim londonCusts = From cust In customers _
                  Where cust.City = "London" _
                  Order By cust.Name Ascending _
                  Select cust.Name, cust.Phone

For more information, see Introduction to LINQ in Visual Basic.

Instead of explicitly specifying a type when you declare and initialize a variable, you can now enable the compiler to infer and assign the type, as shown in the following example. This is referred to as local type inference.


Local type inference works only when you are defining a local variable inside a method body, with Option Infer set to On. On is the default for new projects in LINQ. For more information, see Option Infer Statement.

' The variable number will be typed as an integer. 
Dim aNumber = 5

' The variable name will be typed as a String. 
Dim aName = "Virginia"

In Visual Basic 2005 and earlier, these examples compile, but the type assigned to both aNumber and aName is Object. Therefore, an existing project that is recompiled in Visual Basic 2008, with Option Infer set to On, may behave differently than it did in earlier versions of the language.

' Query example. 
' If numbers is a one-dimensional array of integers, num will be typed 
' as an integer and numQuery will be typed as IEnumerable(Of Integer)-- 
' basically a collection of integers. 

Dim numQuery = From num In numbers _
               Where num Mod 2 = 0 _
               Select num

Variables declared in this manner are strongly typed, just like variables whose type you specify explicitly. Local type inference makes it possible to create anonymous types, which are necessary for LINQ queries, but it can be used for any local variable.

For more information, see Local Type Inference.

Object initializers are used in query expressions when you have to create an anonymous type to hold the results of a query. They also can be used to initialize objects of named types outside of queries. By using an object initializer, you can initialize an object in a single line without explicitly calling a constructor. Assuming that you have a class named Customer that has public Name and Phone properties, along with other properties, an object initializer can be used in this manner:

Dim aCust As Customer = New Customer With {.Name = "Mike", _
                                           .Phone = "555-0212"}

For more information, see Object Initializers: Named and Anonymous Types.

Anonymous types provide a convenient way to temporarily group a set of properties into an element that you want to include in a query result. This enables you to choose any combination of available fields in the query, in any order, without defining a named data type for the element.

An anonymous type is constructed dynamically by the compiler. The name of the type is assigned by the compiler, and it might change with each new compilation. Therefore, the name cannot be used directly. Anonymous types are initialized in the following way:

' Outside a query. 
Dim product = New With {.Name = "paperclips", .Price = 1.29}

' Inside a query. 
' You can use the existing member names of the selected fields, as was 
' shown previously in the Query Expressions section of this topic. 
Dim londonCusts1 = From cust In customers _
                   Where cust.City = "London" _
                   Select cust.Name, cust.Phone

' Or you can specify new names for the selected fields. 
Dim londonCusts2 = From cust In customers _
                   Where cust.City = "London" _
                   Select CustomerName = cust.Name, _
                   CustomerPhone = cust.Phone

For more information, see Anonymous Types.

Extension methods enable you to add methods to a data type or interface from outside the definition. This feature enables you to, in effect, add new methods to an existing type without actually modifying the type. The standard query operators are themselves a set of extension methods that provide LINQ query functionality for any type that implements IEnumerable<T>. Other extensions to IEnumerable<T> include Count, Union, and Intersect.

The following extension method adds a print method to the String class.

' Import System.Runtime.CompilerServices to use the Extension attribute.
<Extension()> _
    Public Sub Print(ByVal str As String)
End Sub

The method is called like an ordinary instance method of String:

Dim greeting As String = "Hello"

For more information, see Extension Methods (Visual Basic).

A lambda expression is a function without a name that calculates and returns a single value. Unlike named functions, a lambda expression can be defined and executed at the same time. The following example displays 4.

Console.WriteLine((Function(num As Integer) num + 1)(3))

You can assign the lambda expression definition to a variable name and then use the name to call the function. The following example also displays 4.

Dim add1 = Function(num As Integer) num + 1

In LINQ, lambda expressions underlie many of the standard query operators. The compiler creates lambda expressions to capture the calculations that are defined in fundamental query methods such as Where, Select, Order By, Take While, and others.

For example, the following code defines a query that returns all senior students from a list of students.

Dim seniorsQuery = From stdnt In students _
                   Where stdnt.Year = "Senior" _
                   Select stdnt

The query definition is compiled into code that is similar to the following example, which uses two lambda expressions to specify the arguments for Where and Select.

Dim seniorsQuery2 = students _
    .Where(Function(st) st.Year = "Senior") _
    .Select(Function(s) s)

Either version can be run by using a For Each loop:

For Each senior In seniorsQuery
    Console.WriteLine(senior.Last & ", " & senior.First)

For more information, see Lambda Expressions.




September 2008

Added link.

Customer feedback.