Few months back while upgrading my project to .NET Framework 3.5 for using LINQ, I had conducted a knowledge sharing session for LINQ. The piece of code and explanation are the parts taken from the knowledge sharing session.

Before we start off with "Getting started with LINQ - Part I", I would like to explain few good things I learnt while working with LINQ. Also I would assume that you are familiar with the Generics, C# 3.0 language enahancements and basics of SQL. If you are unaware of the language enhancement, I would like to recommend visiting MSDN where you wouldfind some good videos about Visual C# 3.0 enahancements. You can also visit a nice blog by Mike Hanley where he quickly reviews most of the C# 3.0 Language enhancements with examples and comparison to C# 2.0. For Genrics you can visit MSDN article "An Introduction to C# Generics".

Introduction

LINQ is not just a query, it stands for "Language Integrated Query" and more than that it is a data iteration engine applied to the language. The iteration engine is inbuilt in the language. LINQ uses mainly IEnumerable<T> for iteration and IQueryable<T> for querying. C# 3.0 enhancements introduced the "var" keyword which is an anonymous type.

var m = new { FirstName = "Manish", LastName = "Singh" };

Notice the use of "var keyword" and "anonymous class". The first thing that should strike in your mind is - "Hey! Is C# still doing the type checking here?" The answer is YES! C# is still doing the type checking here. The first time you use "var" type, it gets intialized with the type inferred from RHS. If you try to change the type of the variable later in the code, C# complains with an error. The CLR is clever enough to shoot off an error message like "Cannot implicitly convert type 'X' to 'Y'." at the design time itself. However, you must be careful in using "var" keyword or else, very quickly you can land up in a mess, with lots of anonymous variable, making it difficult to debug and maintain. The best is, use it when you know the return type can vary and would be decided at runtime. In short, use "var" when you are confused about the return type :-).

LINQ uses deferred query. This means that the query is not performed when the line containing the query is executed. It is performed during the actual enumeration of the object. However, methods like ToList(), ToArray(), Sum(), Max(), Count(), First(), Last() etc is called immediately and are also known as Non-Deferred queries. The advantage of deferred query is that it executes when required and does not apply any extra overload to your code. Non-Deferred queries execute immediately returning an instance of the IEnumerable<T> list. Why? Because C# 3.0 language enhancement allows you to change the data while iterating using the iterator (Not allowed in C# 2.0).

I would show you LINQ using Lamda expressions. Thus, let us have a little introduction to Lamda expression. Lamda expressions are coma-delimited parameter(s) followed by lambda operator "=>", followed by an expression or statement block. e.g. [(param-1, param-2,..., param-N) => expr]. Example: x => x.FirstName.Equals("Manish"). This lambda expression can be read as "x goes to x" or "input x returns x".

For using LINQ for entities your project must be running on framework 3.5, must reference System.Core and you must be having the using directive "System.Linq". Normally, if you use VS 2008 with Framework 3.5 installed, while creating a new project, VS 2008 does all the work for you.

LINQ Console Program
To start add a new project "Sample Data" of type class library in your solution. This is where all our object declaration and initialization takes place. The following image shows the solution explorer with a project "SampleData" in it.

solution explorer

The "SampleData.cs" int the "SampleData" project includes a classical example of Customer, Product, Order and OrderItem. For the sake of simplicity, I have declared the properties as "public".

SampleData.cs
 The "DataContext.cs" int the "SampleData" project includes the initialization code for Customer, Product, Order and OrderItem. For the sake of simplicity, I have declared all methods static for the sake of simplicity. This method is required from my console program to collect some meaningful data for "Customer", "Product", "Order" and "OrderItem". The next section shows you a sample initialization.

DataContext.cs

To initialize the entities with some sample data you may create the object with fictitious but meaningful data and assign it to a list as shown in the image below. Later we will query these data and check the output.

DataContext.cs

Next, we add a new console project into your solution say "LINQ-Object". Add Reference to "SampleData" project. In the "Program.cs" file that is created by VS 2008 for you, go ahead and declare a bunch of static methods as explained below. After that you can call each of these from the "static void Main(string[] args)" method and check the output. Also try to use break point and see what is displayed.

LINQ: Select
SelectMost of the extension methods of LINQ applied on IQueryable<T> or IEnumerable<T> returns another IQueryable<T> or IEnumerable<T>. This allows you to nest the methods in progressive manner like "Append()" method of "StringBuilder" class. I have purposefully applied nested select to explain this. Select is a deferred query and parsing is done at the runtime.

Output

LINQ: Where Clause
WhereIn this part of the code I have explained a simple "where" clause using LINQ. The query simply returns all customer who belong to "category", "A". If you see the declaration of "Customer" entity explained earlier, you would see that it has an attribute "category" to help categorize the customers into groups depending on their importance.

Output

LINQ: Join
JoinIn this part of the code "Customer" and "Order" to see the customer's full name, order name and order date. When you run the program the output (see image below) would be shown, depending on your data.

Output

LINQ: Group Join
Group JoinIn this part "Customer", "Order" and "OrderItem" is joined to see the customer full name, customer category, order name and order details like product name, quantity and price. When you run the program the output (see image below) would be shown, depending on your data.

Output

LINQ: Group By
Group ByThis part of the code, returns the customers grouped by their category. When using "Group By" extension method in LINQ, it returns a two dimensional list. Each elements of the outer list contains a list of customers belonging to the same group.

Output

LINQ: Order By
Order ByThis section explains the "Order By" clause as seen in SQL. You can have multiple attributes in the "Order By" clause and also provide sorting direction.

Output

LINQ: TakeWhile
TakeWhile"Take" extension method allows you to select items from top while the TakeWhile extension method allows you to select items based on certain condition. The code selects items whose string length is below six.

Output

LINQ: Skip
Skip"Skip" extension method allows you to skip items from top while the SkipWhile extension method allows you to skip items based on certain condition. The code skips five items from the top.

Output

There are several more methods defined in LINQ. I would encourage you to apply more of these extension menthods for practice and clarity.