Introduction
LINQ is a set of language extensions added to C# and VB.NET which makes queries a first-class concept to these languages. It provides a unified programming model to different data domains for data management. As I mentioned in my first post, using LINQ we can query and operate on different data domains including relational databases, XML, custom entities, DataSets or any third party data source. Above all, the concept of queries is now applicable to in-memory data as opposed to using queries with a persistent medium only. From a developer’s point of view, the interface to each data domain remains the same. But the LINQ engine is responsible for converting the queries to target the domain being referenced.
Since LINQ is a first-class concept in C# and VB.NET, these languages come loaded with support for LINQ. LINQ queries take advantage of features including IntelliSence and compile-time syntax checking. LINQ queries rely on standard query operators (discussed shortly) which are a set of functions used to fetch, parse, sort and filter the data.
Query Expression and Method-Based Queries
A LINQ query is a reminiscent of standard SQL-Query syntax. The purpose of LINQ is to add data querying capabilities to the .NET Framework such that any data-domain can be processed with the same ease. LINQ relies on concepts including Extension Methods, Anonymous Types, Anonymous Methods and Lambda Expressions discussed in earlier posts.
A LINQ Query is also known as Query Expression or Query Syntax. A query expression is a declarative syntax for writing queries which allows us to filter, group and order data. According to MSDN, “a query expression operates on one or more information sources by applying one or more query operators from either the standard query operators or domain-specific operators”. This means that LINQ can operate on different data-domains using operators specific to LINQ or developed by a third party. To me this is a polymorphic behavior of LINQ. The result of a query expression is an in-memory sequence of elements (or objects). Any object which implements the IEnumerable
Let us see a simple example in listing 1 which shows a LINQ Query in action:
Listing 1
view plainprint?
1. int [] prime = new int [8] {1, 3, 5, 7, 11, 13, 17, 19}; // Line 1
2.
3. var primeNumbers = // Line 2
4. from p in prime // Line 3
5. where p > 0 // Line 4
6. select p; // Line 5
7.
8. foreach (int p in primeNumbers) // Line 6
9. {
10. // use p
11. }
int [] prime = new int [8] {1, 3, 5, 7, 11, 13, 17, 19}; // Line 1
var primeNumbers = // Line 2
from p in prime // Line 3
where p > 0 // Line 4
select p; // Line 5
foreach (int p in primeNumbers) // Line 6
{
// use p
}
In the above listing, a list of prime numbers is queried and the result is assigned to a variable primeNumbers. The LINQ Query (line 2–5) resembles a SQL statement with the standard from, where and select clauses. But it is being applied to an in-memory collection of numbers rather than a persistent medium (such as database or XML). Although simple but I am sure you can visualize the strength of LINQ upfront from the above example. The rest of the example is what we talked about (var, foreach) in the previous post.
A query expression can also be represented by a Method-based Query syntax. A method-based query utilizes extension methods and lambda expression. It is a rather concise way of writing query expressions. There is no performance difference between the two. A query expression is more readable while a method-based query is concise to write. It really comes down to your choice of syntax. But do keep in mind that all query expressions are translated into method-based queries. Using method-based query, listing 1 can be written as following:
Listing 2
view plainprint?
1. IEnumerable
2. prime
3. .Where (p => p > 0)
4. .Select (p => p);
IEnumerable
prime
.Where (p => p > 0)
.Select (p => p);
Avid readers must have figured out the reason for applying the foreach loop on the variable primeNumbers in listing 1. This is because the type primeNumbers is converted to IEnumerable
I am sure by now you can spot many of the features explained in part 2 and part 3 of this series. The above queries are just making use of concepts including var keyword, extension methods, lambda expressions and enumerators.
LINQ Syntax
LINQ is a reminiscent of standard SQL Language and thus has a sharp resemblance to it. Like its counterpart, query expression consists of clauses. There are three main clauses in a LINQ expression including from, select and the where clause. The general syntax of a LINQ query is as following:
var [query] = from …
where …
select …
The first clause in a LINQ Query is the from clause. You may be wondering why a LINQ query begins with the from clause unlike a standard SQL query which is preceded by the select clause. The reason for this precedence is to support Intellisence when working with Visual Studio IDE. Since the from clause specifies the data source ahead of the query, the compiler becomes data-source aware and hence supports Intellisence. The from clause is then followed by the where and select clauses. You can find the full syntax of a LINQ Query here .
Let us see listing 3 to analyze a LINQ query piece by piece. We start by defining a simple class followed by object initialization:
Listing 3
view plainprint?
1. public class Car
2. {
3. public string Type { get; set; }
4. public string Color { get; set; }
5. }
6.
7. Car[] cars =
8. {
9. new Car { Type = "SUV", Color = "Green" },
10. new Car { Type = "SUV", Color = "Black" },
11. new Car { Type = "4x4", Color = "Red" },
12. new Car { Type = "Truck", Color = "Orange" },
13. new Car { Type = "Jeep", Color = "Black"}
14. };
public class Car
{
public string Type { get; set; }
public string Color { get; set; }
}
Car[] cars =
{
new Car { Type = "SUV", Color = "Green" },
new Car { Type = "SUV", Color = "Black" },
new Car { Type = "4x4", Color = "Red" },
new Car { Type = "Truck", Color = "Orange" },
new Car { Type = "Jeep", Color = "Black"}
};
Now that we have an array of cars with their properties initialized, we use a LINQ Query to find all the cars with a specific make:
view plainprint?
1. IEnumerable
2. from myCar in cars
3. where myCar.Type == "SUV"
4. select myCar;
IEnumerable
from myCar in cars
where myCar.Type == "SUV"
select myCar;
The query begins with the from clause. A from clause only operates on sequences implementing the IEnumerable interface. This clause is actually made up of two parts; from and in. The in part points to the source-sequence which must be of type IEnumerable while the from part is a variable used for iterating through the source-sequence.
Next is the where clause used for filtering. Behind the scene, this clause is converted to Where Query Operator which is a member of the Enumerable class. This method accepts a lambda expression as parameter to apply the filter.
Next in the sequence is the select clause. This clause defines an expression which is assigned to a variable. The expression can be of any type including an instance of a class, string, number, boolean etc. Indeed this clause lets a type be created on the fly and assigned to a variable.
Finally, we can iterate through the variable ‘search’ since it is of type IEnumerable using the following code:
view plainprint?
1. foreach (Car c in search)
2. {
3. // use c.Type, c.Color
4. }
foreach (Car c in search)
{
// use c.Type, c.Color
}
Standard Query Operators
So far we have hardly scratched the surface of LINQ syntax and have seen some very simple LINQ queries, but in reality; the discussion of query expressions is incomplete without Standard Query Operators. The standard query operators represent an API defined in the Enumerable and Queryable classes under the System.Linq namespace. These operators are extension methods which accept lambda expressions as argument. These operators operate on sequences where any object which implements the IEnumerable
I have stated above that a query expression is converted to a method-based query. In a method-based query, a Clause is converted to its respective Standard Query Operator (an extension method) . For example, the where clause is converted to a Where operator while the select clause is converted to a Select Operator. To keep it simple, just remember that the same clause in a query expression is represented by an operator when converted to a method-based query.
According to LINQ’s official documentation, Standard Query Operators can be categorized into the following:
• Restriction operators
• Projection operators
• Partitioning operators
• Join operators
• Concatenation operator
• Ordering operators
• Grouping operators
• Set operators
• Conversion operators
• Equality operator
• Element operators
• Generation operators
• Aggregate operators
Monday, January 11, 2010
Introduction of LinQ for VS 2010
Subscribe to:
Post Comments (Atom)
1 comments:
damn good job
Post a Comment