Showing posts with label Linq. Show all posts
Showing posts with label Linq. Show all posts

Sunday, January 29, 2012

C# 3.0 for Beginners - Query Execution in LINQ

The execution of queries written is different from what a new LINQ user would perceive it to be. The query isn’t evaluated and the result is not stored in the query variable until the foreach iteration (where the values are actually required) or a manual iteration using the underlying GetEnumerator and MoveNext methods. The query variable only stores the query commands. This is concept is referred to as deferred execution.
public static void GetIExplorer()
{
    //  1. Data Source
    Process[] processes = Process.GetProcesses();

    //  2. Query Creation
    IEnumerable<int> query =
       from p in processes
       where p.ProcessName.ToLower().Equals("iexplore")
       select p.Id;

    //  3. Query execution
    //  This is the part where the query is evaluated
    //  and result is stored in the query variable.
    foreach (int pid in query)
    {
        Console.WriteLine("Process Id : "+pid);
    }
}

As the query variable doesn’t store the results, you can execute it as many times as you like. If a data source is updated at regular intervals, you could retrieve the latest results every time you iterate over the query variable.


The figure shown above shows information about the query variable ‘query’. The Results View section shows the results of query execution and it also informs the user that “Expanding the Results View will enumerate the IEnumerable” i.e. perform the query execution for debugging.

Forcing immediate execution of queries
Immediate execution of queries is forced for queries that perform aggregation functions over the data retrieved from query evaluation. These functions include Count, Max, Min, Average etc. These queries execute without an explicit foreach statement because the query itself would use a foreach statement to calculate the result.

The following query returns the number of processes identified as “IExplore.exe”.
//  Calculate the number of "iexplore" processes
int numberOfProcesses = query.Count();

Execution results can be cached (if need be) for temporary processing using the ToList() and ToArray() methods as shown below:
//  Caching results using ToList() and ToArray() methods.
List<int> queryResult =
(from p in processes
    where p.ProcessName.ToLower().Equals("iexplore")
    select p.Id).ToList();

Array inferredQueryResult =
    (from p in processes
    where p.ProcessName.ToLower().Equals("iexplore")
    select p.Id).ToArray();


C# 3.0 for Beginners - Learning LINQ - An Overview

I’m probably quite late to provide an overview on LINQ, which is by now a lot more popular than the time when I actually had started hearing about it.

Well, this is expected to be a series of posts that would help other rookies like me who haven’t yet started learning LINQ yet. So, lets get started. To begin with I’m providing here an overview of LINQ (Language Integrated Query).

LINQ was introduced by Microsoft with the objective to reduce the complexity of accessing and integrating information. With the LINQ project, Microsoft has added query facilities to the .Net Framework that apply to all sources of information, not just relational or XML data. Everyday programmers write code that accesses a data source using looping and/or conditional constructs etc. The same constructs can be written using query expressions that are far lesser in code size. LINQ makes it possible to write easily readable and elegant code. The examples that follow will imply how easily understandable LINQ code can be.

LINQ defines a set of standard query operators that you can use for traversal, filter and projection operations. These standard operators can be applied to any IEnumerable<T> based information source. The set of standard query operators can be augmented with new domain-specific operators that are more suitable for the target domain or technology. This extensibility in the query architecture is used in the LINQ project itself to provide implementations that work over both XML (LINQ to XML) and SQL (LINQ to SQL) data. Lets write some code to understand the query operators in more detail:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;

/// <summary>
/// Using standard query operators.
/// </summary>
public static void GetIExplorer()
{
    //  1. Data Source
    Process[] processes = Process.GetProcesses();

    //  2. Query Creation
    IEnumerable<int> query = from p in processes
                             where p.ProcessName.ToLower().Equals("iexplore")
                             select p.Id;

    //  3. Query execution
    foreach (int pid in query)
    {
        Console.WriteLine("Process Id : "+pid);
    }
}

All LINQ query operations consist of three distinct operations:

Identify the data source
Query creation
Query execution

Calling the method would show you the currently running Internet Explorer processes (their process ids). The heart of the method lies in the following statement of our program.
IEnumerable<int> query = from p in processes
                         where p.ProcessName.ToLower().Equals("iexplore")
                         select p.Id;

The expression on the right hand side of this statement is called the query expression. The output of this expression is held in the local variable ‘query’. The query expression operates on one or more information sources by applying the query operators from the standard or domian specific set of query operators. We have used standard query operators here namely where and select.

The from clause select the list of processes which becomes the input for the where operator which filters the list and selects only those elements that satisfy the condition specified with the where operator. The selected elements are then processed by the select operator that determines any specific information selection for each element.

The above statement can also be written using explicit syntax as shown below:
IEnumerable<int> query = Process.GetProcesses()
               .Where(s => s.ProcessName.ToLower().Equals("iexplore"))
               .Select(s => s.Id);

This form of query is called a method-based query and the arguments to the query operators are called lambda expressions. They allow query operators to be defined individually as methods and are connected using the dot notation. I will deal with lambda expressions in my following posts.