LINQ Query Expressions

At first glance, LINQ query expressions look a lot like SQL expressions. But make no mistake: LINQ is not SQL. For starters, LINQ is strongly typed. After all, C# is a strongly typed language, and therefore, so is LINQ. The language adds several new keywords for building query expressions. However, their implementation from the compiler standpoint is pretty simple. LINQ query expressions typically get translated into a chain of extension method calls on a sequence or collection. That set of extension methods is clearly defined, and they are called standard query operators.

This LINQ model is quite extensible. If the compiler merely translates query expressions into a series of extension method calls, it follows that you can provide your own implementations of those extension methods. In fact, that is the case. For example, the class System.Linq.Enumerable provides implementations of those methods for LINQ to Objects, whereas System.Linq.Queryable provides implementations of those methods for querying types that implement IQueryable<T> and are commonly used with LINQ to SQL.

This LINQ model is quite extensible. If the compiler merely translates query expressions into a series of extension method calls, it follows that you can provide your own implementations of those extension methods. In fact, that is the case. For example, the class System.Linq.Enumerable provides implementations of those methods for LINQ to Objects, whereas System.Linq.Queryable provides implementations of those methods for querying types that implement IQueryable<T> and are commonly used with LINQ to SQL.

Let’s jump right in and have a look at what queries look like. Consider the following example, in which I create a collection of Employee objects and then perform a simple query:
<pre class="brush:csharp">
using System;
using System.Linq;
using System.Collections.Generic;

public class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Decimal Salary { get; set; }
public DateTime StartDate { get; set; }
}

public class SimpleQuery
{
static void Main() {
// Create our database of employees.
var employees = new List<Employee> {

new Employee {
FirstName = "Joe",
LastName = "Bob",
Salary = 94000,
StartDate = DateTime.Parse("1/4/1992") },
new Employee {
FirstName = "Jane",
LastName = "Doe",
Salary = 123000,
StartDate = DateTime.Parse("4/12/1998") },
new Employee {
FirstName = "Milton",
LastName = "Waddams",
Salary = 1000000,
StartDate = DateTime.Parse("12/3/1969") }
};

var query = from employee in employees
where employee.Salary > 100000
orderby employee.LastName, employee.FirstName
select new { LastName = employee.LastName,
FirstName = employee.FirstName };
Console.WriteLine( "Highly paid employees:" );
foreach( var item in query ) {
Console.WriteLine( "{0}, {1}",
item.LastName,
item.FirstName );
}
}
}
</pre>
First of all, you will need to import the System.Linq namespace, as I show in the following section titled "Standard Query Operators." In this example, I marked the query expression in bold to make it stand out. It’s quite shocking if it’s the first time you have seen a LINQ expression! After all, C# is a language that syntactically evolved from C++ and Java, and the LINQ syntax looks nothing like those languages.

Prior to the query expression, I created a simple list of Employee instances just to have some data to work with. Each query expression starts off with a from clause, which declares what’s called a range variable. The from clause in our example is very similar to a foreach statement in that it iterates over the employees collection and stores each item in the collection in the variable employee during each iteration. After the from clause, the query consists of a series of clauses in which we can use various query operators to filter the data represented by the range variable. In my example, I applied a where clause and an orderby clause, as you can see. Finally, the expression closes with select, which is a projection operator. When you perform a projection in the query expression, you are typically creating another collection of information, or a single piece of information, that is a transformed version of the collection iterated by the range variable. In the previous example, I wanted just the first and last names of the employees in my results.

Another thing to note is my use of anonymous types in the select clause. I wanted the query to create a transformation of the original data into a collection of structures, in which each instance contains a FirstName property, a LastName property, and nothing more. Sure, I could have defined such a structure prior to my query and made my select clause instantiate instances of that type, but doing so defeats some of the convenience and expressiveness of the LINQ query. And most importantly, as I’ll detail a little later in the section "The Virtues of Being Lazy," the query expression does not execute at the point the query variable is assigned. Instead, the query variable in this example implements IEnumerable<T>, and the subsequent use of foreach on the query variable produces the end result of the example.

The end result of building the query expression culminates in what’s called a query variable, which is query in this example. Notice that I reference it using an implicitly typed variable. After all, can you imagine what the type of query is? If you are so inclined, you can send query.GetType to the console and you’ll see that the type is as shown here:
<pre class="brush:csharp">
System.Linq.Enumerable+<SelectIterator>d__b`2[Employee, ?
<>f__AnonymousType0`2[System.String,System.String]]
</pre>
For those of you familiar with SQL, the first thing you probably noticed is that the query is backward from what you are used to. In SQL, the select clause is normally the beginning of the expression. There are several reasons why the reversal makes sense in C#. One reason is so that Intellisense will work. In the example, if the select clause appeared first, Intellisense would have a hard time knowing which properties employee provides because it would not even know the type of employee yet.


Source Of Information : Apress Accelerated C Sharp 2010

0 comments


Subscribe to Developer Techno ?
Enter your email address:

Delivered by FeedBurner