Advanced ASP.NET : LINQ and the Entity Framework - LINQ Basics

6/23/2011 4:10:38 PM

1. Understanding LINQ

LINQ defines keywords that you can use to select, filter, sort, group, and transform data. The minor miracle of LINQ is that different LINQ providers allow these keywords to work with different types of data. Here's a summary of the LINQ providers that are included with .NET 4:

LINQ to Objects:

This is the simplest form of LINQ. It allows you to query collections of in-memory objects (such as an array, an ArrayList, a List, a Dictionary, and so on).

Parallel LINQ:

This is a variation of LINQ to objects that has built-in support for multithreaded execution. That means you can use it to speed up intensive searches on in-memory collections—if your web server has multiple CPU cores.

LINQ to DataSet:

This form of LINQ resembles LINQ to objects, except it digs DataRow objects out of a DataTable.


This form of LINQ allows you to search the elements contained in an XElement or XDocument . In other words, it allows you to perform more powerful searches when dealing with in-memory XML data.


This is the original LINQ provider for data access. It allows you to fetch data from a SQL Server database. Although LINQ to SQL still exists in .NET 4, it's been superseded by LINQ to Entities, which offers the same features with fewer limitations.

LINQ to Entities:

Like LINQ to SQL, LINQ to Entities allows you to perform database queries with a LINQ expression. Unlike LINQ to SQL, it supports a range of database software—anything that has an ADO.NET provider—and it gives you more options for mapping tables to differently structured objects.

In addition to these providers, third-party developers have created many of their own. For example, there are LINQ providers for searching Amazon's product catalog, Active Directory, Excel documents, Google search results, Flickr images, and more.


LINQ is a deeply integrated part of .NET and the VB language. However, it isn't an ASP.NET-specific feature, and it can be used equally well in any type of .NET application, from command-line tools to rich Windows clients.

2. LINQ Basics

The easiest way to approach LINQ is to consider how it works with in-memory collections. This is LINQ to Objects—the simplest form of LINQ.

First, imagine you have some sort of data class, like the Employee class shown here:

Public Class Employee

Public Property EmployeeID() As Integer
Public Property FirstName() As String
Public Property LastName() As String
Public Property TitleOfCourtesy() As String

Public Sub New(ByVal employeeID As Integer, ByVal firstName As String, _
ByVal lastName As String, ByVal titleOfCourtesy As String)
Me.EmployeeID = employeeID
Me.FirstName = firstName
Me.LastName = lastName
Me.TitleOfCourtesy = titleOfCourtesy
End Sub
End Class

This exceedingly simple class includes just four properties and a basic constructor. You can easily create a collection that consists of Employee objects, like the strongly typed List shown here:

' Create the collection.
Dim employees As New List(Of Employee)()

' Fill the collection.
employees.Add(New Employee(1, "Nancy", "Davolio", "Ms."))

employees.Add(New Employee(2, "Andrew", "Fuller", "Dr."))
employees.Add(New Employee(3, "Janet", "Leverling", "Ms."))

In this example, the data for each Employee object is hard-coded, but you could just as easily read it from an XML document, a database, or some other location. The key point is that when you're finished, you're left with some sort of collection that contains one or more objects. You can then use LINQ to Objects to get at the data in your collection.

Before you use a LINQ expression, it's worth considering the traditional approach for searching a collection.

For example, imagine you want to get a list of all employees who have a last name that starts with the letter D. The traditional approach is to use code to loop through the full collection of employees and add each matching employee to a second collection, as shown here:

' Create the source collection.
Dim employees As New List(Of Employee)()
' (Code for filling the collection omitted to save space.)

' Find the matching employees.
Dim matches As New List(Of Employee)()
For Each employee As Employee In employees
If employee.LastName.StartsWith("D") Then
End If

You can then carry on to perform another task with the collection of matches or display it in a web page, as shown here:

gridEmployees.DataSource = matches

Essentially, LINQ to Objects allows you to replace iterative logic (such as a For Each block) with a declarative expression. The following example shows how you can rewrite the earlier example, replacing the For Each block with a LINQ expression that queries the collection:

' Create the source collection.
Dim employees As New List(Of Employee)()
' (Code for filling the collection omitted to save space.)

Dim matches = From employee In employees
Where employee.LastName.StartsWith("D")
Select employee

gridEmployees.DataSource = matches

The end result is essentially the same—you wind up with a collection named matches that's filled with employees who have last names starting with D, which is then displayed in a grid (see Figure 1).

Figure 1. Filtering a list of employees with LINQDissecting the Code . . .

  • The LINQ expression uses a set of new keywords, including From, In, Where, and Select. You shape your query using these keywords. (You'll see some of the rules of expression building starting in the next section.)

  • The VB compiler is intelligent enough to figure out that the LINQ expression is a single code statement, even though it's spread over multiple lines. You could add an underscore at the end of each line to make this detail explicit, but the code is cleaner if you don't.

  • LINQ expressions return an usual type of object, called an iterator object. (In this example, the iterator object is named matches.) Although the iterator object looks like an ordinary collection to your code, it doesn't actually hold any information. Instead, it has the ability to fetch the data when you need it. So when you examine the contents of an iterator object with a For Each block or when you bind it to a control, LINQ evaluates your expression and quickly grabs the information you need. This trick is called deferred execution.


    There's no technical reason why LINQ needs to use deferred execution, but there are many reasons why it's a good approach. In many cases, it allows LINQ to use performance optimization techniques that wouldn't otherwise be possible. For example, when using database relationships with LINQ to Entities, you can avoid loading related data that you don't actually use.

  • In this example, the iterator object (named matches) is defined without using an explicit data type. This is a shortcut that tells the VB compiler to use the correct data type, without forcing you to specify it. Technically, the iterator object could be one of several different types of objects depending on the clauses you use in the LINQ expression. But all of these objects implement the strongly typed version of the IEnumerable interface. In this example, that means you can explicitly use the data type IEnumerable(Of Employee), because the collection holds Employee objects, if you don't mind the additional complexity. However, either way the compiled code is exactly the same. If you leave out the data type, the compiler adds the data type information to your compiled page automatically (although you never see this detail).

    You don't need to know the specific iterator class that your code uses because you interact with the results through the strongly typed IEnumerable interface. But if you're curious, you can determine the object type at runtime using the Visual Studio debugger (just hover over the variable while in break mode).

  • At this point, you might be wondering how LINQ actually does its filtering work. The answer depends on the type of data you're querying. For example, LINQ to Entities transforms LINQ expressions into database commands. As a result, the LINQ to Entities plumbing needs to open a connection and execute a database query to get the data you're requesting. But if you're using LINQ to Objects, as in the previous example, the process that LINQ performs is much simpler. In fact, in this case, LINQ simply uses a For Each loop to scan through your collections, traveling sequentially from start to finish. Although this isn't any different from the approach you used in the first place, it does open up many more possibilities as you use more complex expressions.

2.1. LINQ Expressions

Before you can go much further with LINQ, you need to understand how a LINQ expression is composed. LINQ expressions have a superficial similarity to SQL queries, although the order of the clauses is rearranged.

All LINQ expressions must have a From clause that indicates the data source and a Select clause that indicates the data you want to retrieve (or a Group clause that defines a series of groups into which the data should be placed). The From clause is placed first:

Dim matches = From employee In employees

The From clause identifies two pieces of information. The word immediately after In identifies the data source—in this case, it's the collection object named employees that holds the EmployeeDetails instances. The word immediately after From assigns an alias that represents individual items in the data source. For the purpose of the current expression, each EmployeeDetails object is named employee. You can then use this alias later when you build other parts of the expression, such as the filtering and selection clauses.

Here's the simplest possible LINQ query. It simply retrieves the full set of data from the employees collection:

Dim matches = From employee In employees
Select employee

The VB language includes many more LINQ operators that won't be considered in detail in this book. In the following sections, you'll tackle the most important operators, including Select, Where, and OrderBy. You can review all the LINQ operators in the Visual Studio Help. You can also find a wide range of expression examples on Microsoft's 101 LINQ Samples page at

2.1.1. Projections

You can change the Select clause to get a subset of the data. For example, you could pull out a list of first name strings like this:

Dim matches = From employee In employees
Select employee.FirstName

or a list of strings with both first and last names:

Dim matches = From employee In employees
Select employee.FirstName + employee.LastName

As shown here, you can use standard VB operators on numeric data or strings to modify the information as you're selecting it. This changes the type of collection that's returned—it's now an IEnumerable(Of String) collection of strings, rather than a collection of Employee objects. But because this code defines the matches variable without an indicated data type, the code keeps working without a hitch.

Even more interestingly, you can dynamically define a new class that wraps just the information you want to return. For example, if you want to get both the first and last names but you want to store them in separate strings, you could create a stripped-down version of the EmployeeDetails class that includes just a FirstName and LastName property. To do so, you use a VB feature known as anonymous types. The basic technique is to add the New With keywords to the Select clause, followed by a pair of curly braces. Then, inside the braces, you assign each property you want to create in terms of the object you're selecting.

Here's an example:

Dim matches = From employee In employees
Select New
With {.First = employee.FirstName, .Last = employee.LastName}

This expression, when executed, returns a set of objects that use an implicitly created class. Each object has two properties: First and Last. You never see the class definition, because it's generated by the compiler and given a meaningless, automatically created name. (And for that reason, you can't pass instances of the automatically generated class to other parts of your code.) However, you can still use the class locally, access the First and Last properties, and even use it with data binding (in which case ASP.NET extracts the appropriate values by property name, using reflection). The ability to transform the data you're querying into results with a different structure is called projection.

Figure 2 shows the result of binding the matches collection to a GridView.

Figure 2. Projecting data to a new representation

Of course, you don't need to use anonymous types when you perform a projection. You can define the type formally and then use it in your expression. For example, if you created the following EmployeeName class:

Public Class EmployeeName
Public Property FirstName() As String
Public Property LastName() As String
End Class

you could change EmployeeDetails objects into EmployeeName objects in your query expression like this:

Dim matches = From employee In employees
Select New EmployeeName With
{.FirstName = employee.FirstName, .LastName = employee.LastName}

This query expression works because the FirstName and LastName properties are publicly accessible and aren't read-only. After creating the EmployeeName object, LINQ sets these properties. Alternatively, you could add a set of parentheses after the EmployeeName class name and supply arguments for a parameterized constructor, like this:

Dim matches = From employee In employees
Select New EmployeeName(FirstName, LastName)

2.1.2. Filtering and Sorting

In the first LINQ example in this article, you saw how a where clause can filter the results to include only those that match a specific condition. For example, you can use this code to find employees who have a last name that starts with a specific letter:

Dim matches = From employee In employees
Where employee.LastName.StartsWith("D")
Select employee

The Where clause takes a conditional expression that's evaluated for each item. If it's True, the item is included in the result. However, LINQ keeps the same deferred execution model, which means the where clause isn't evaluated until you actually attempt to iterate over the results.

As you probably already expect, you can combine multiple conditional expressions with the And and Or operators, and you can use relational operators (such as <, <=, >, and >=) in conjunction with hard-coded values or other variables. For example, you could create a query like this to filter out products greater than a certain price threshold:

Dim matches = From product In products
Where product.UnitsInStock > 0 And product.UnitPrice > 3.00
Select product

One interesting feature of LINQ expressions is that you can easily call your own methods inline. For example, you could create a function named TestEmployee() that examines an employee and returns True or False based on whether you want to include it in the results:

Private Function TestEmployee(ByVal employee As Employee) As Boolean
Return employee.LastName.StartsWith("D")
End Function

You could then use the TestEmployee() method like this:

Dim matches = From employee In employees
Where TestEmployee(employee)
Select employee

The Order By operator is equally straightforward. It's modeled after the syntax of the Select statement in SQL. You simply provide a list of one or more values to use for sorting, separated by commas.

Here's a basic sorting example:

Dim matches = From employee In employees
Select employee
Order By employee.LastName, employee.LastName

You can also add the word Descending after a field name to sort in the reverse order:

Dim matches = From employee In employees
Select employee
Order By employee.LastName Descending, employee.LastName Descending

There's far more that you can learn about LINQ expressions. In fact, entire books have been written on LINQ alone, including the comprehensive Pro LINQ: Language Integrated Query in C# 2008 (Apress). But you now know the essentials of LINQ expressions, which is enough to let you use it with another remarkable .NET feature: the Entity Framework.

PS4 game trailer XBox One game trailer
WiiU game trailer 3ds game trailer
Top 10 Video Game
-   F1 2015 | Features Trailer
-   Battle Fantasia Revised Edition | Debut Trailer for Steam
-   Victor Vran [PC] Story Trailer
-   Star Wars Battlefront PC Alpha footage
-   Skyforge [PC] Open Beta Gameplay Trailer
-   Armored Warfare [PC] PvE Trailer
-   F1 2015 [PS4/XOne/PC] Features Trailer
-   Act of Aggression [PC] Pre-Order Trailer
-   Sword Coast Legends [PC] Campaign Creation E3 2015 Trailer
-   Sword Coast Legends [PC] Campaign Creation E3 2015 Dungeon Run Trailer
-   Naruto Shippuden: Ultimate Ninja Storm 4 Trailer
-   Danganronpa Another Episode: Ultra Despair Girls Trailer 2
-   Project X Zone 2 Trailer
-   Poly Bridge Early Access Trailer
-   Rodea The Sky Soldier Trailer
Game of War | Kate Upton Commercial