LINQ stands for Language Integrated Query and is part of the C# 3.0 framework. In this article Piyali Sengupta gives us an introduction to the LINQ technology.

Introduction:

You must have noticed that we use Structured Query Language (SQL) to query, modify and define the database and some procedural or object oriented language like C# or VB to work with the interface of our application. This requires a different layer to connect and work with the database, called Data Access Layer (DAL). So our problem domain is modeled with objects and inside these objects the data access layer works for interfacing the database and thus integrates the object model with a relational schema. For complex and large applications this approach is alright but for simpler applications this is a costlier option.
LINQ addresses this problem and allows operating on data stores at a higher conceptual level. How? The same way SQL did. The relational operators like Select, Project, Join, Group, Partition, Set operations etc., are also implemented in LINQ. So C# and VB compilers in the .Net framework 3.5 which support the LINQ syntax makes it possible to work with a configured data store without resorting to ADO.Net.

If you want to query the Customers table in Northwind database, using LINQ query in C#, it would look like:

var data = from c in dataContext.Customers
        where c.Country == “Spain”
        select c;


in VB,

Dim data = From c In dataContext.Customers
        Where c.Country = “Spain”
        Select c


• The from keyword logically loops through the contents of the collection.
• The expression with the where keyword is evaluated for each object in the collection.
• The select statement selects the evaluated object to add to the list being returned.
• The var keyword is for variable declaration. Since the exact type of the returned object is not known, it indicates that the information will be inferred dynamically.

LINQ Query Syntax: The Relational Operators:

LINQ expressions can be used both to query and update data from any supported data source. There are two ways of writing LINQ operations:
• Through query expressions
• Through method calls

Both these approaches are functionally and performance-wise same, but query expressions are definitely more readable.

//using LINQ query

var data = from c in db.Customers
        where c.Country == “Spain”
        select c;

// using method call

var data = db.Customers.Where(c => c.Country == “Spain”)


The => operator indicates a lambda expression, i.e., an inline expression used when a delegate type is expected. The => operator is read as “goes to” or “such that”. Its left side indicates input parameters, whereas the right side of the operator has the block of statements to execute. These lambda operators are used in LINQ to create delegates. This somehow reminds me of Relational Calculus, what about you?

Projection Operator:

The Select operator is used for projection of any data source to memory. It is used with thefrom keyword.

when applied on a data set:

 int[] numbers = { 15, 24, 71, 43, 9, 28, 36 };

    var addOne =
        from n in numbers
        select n + 1;
   
    Console.WriteLine("Numbers + 1:");
    foreach (var i in addOne)
        Console.WriteLine(i);

when applied on a SQL table:

var data = from c in Customers
        where c.Country == “Spain”
        orderby c.CompanyName, c.ContactName
        select c;



Joining and Grouping:

The Join operator executes an inner join of two collections using a matching key that the two collections share.

var data = from c in Customers
          join o in orders
        on c.CustomerID equals o.CustomerID
        select new {c.Name, o.OrderNumber};


the group clause returns a sequence of root objects, known as grouping objects, that contain zero or more items that match the key value for the group. So, the output of a grouping operation will not be immediately bindable to data-bound controls.

var data = from c in customers
 group c.ContactName by
     new { City = c.City, Region = c.Region} into g
    where g.Count() > 1;
   select g



Aggregation Operator:

There are a number of aggregation operators such as Count, Sum, Average, Min and Max.

For example:

int[] numbers = { 2, 2, 3, 5, 5 , 7, 8};
   int uniqueNumbers = numbers.Distinct().Count();
   Console.WriteLine("There are {0} unique Number in the set.", uniqueNumbers);


let, us look into another example involving the Aggregate operator, which involves a given function over the elements of a collection. Each iteration can save a value into an internal buffer; at the end of the loop, the current value is returned.

var data = from c in Customers
          join o in orders
        on c.CustomerID equals o.CustomerID
        select new {
c.CompanyName, MaxAmount = orders.Aggregate(
(t,s) => t.OrderDate > s.OrderDate ? t : s) };


This will return a collection of objects pairing the company name with date of most recent order.

Partitioning Operator:

The Take operator is used to return a given number of elements in a list.

int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
           var first_five = numbers.Take(5);
           
            Console.WriteLine("First 5 numbers:");
            foreach (var i in first_five) {
                Console.WriteLine(i);


let us take another example on Customers table:

 var data = ( from c in Customers
               select c).Take(10);



The Skip operator is used to jump over a given number of elements in a sequence.

For example:
int[] numbers = { 5, 4, 6, 3, 2, 8, 5, 7, 2, 7 };
           
            var skip4num = numbers.Skip(4);
           
            Console.WriteLine("All but first 4 numbers:");
            foreach (var i in skip4num) {
                Console.WriteLine(i);


this will return the values: 2, 8, 5, 7, 2, 7

The list of LINQ operators is much longer than discussed over here. I would suggest you to check the online documentation for more information and examples. Let us discuss the mechanics of LINQ before we sign off.

The Layers of LINQ:

LINQ can deal with relational data, as well as XML documents. It requires an underlying layer of code that maps from the high-level command syntax to the actual query syntax of the data store. The query operators provided by LINQ can work on in-memory instance of any .Net type, which could be queried. A .Net type is query-able when it implements the IEnumerable interface.
When you work with in-memory objects such as data sets and collections, they are already loaded in the memory. But when you work with a database a layer of LINQ establishes the connection to the database and maps the query to the query language of the database.

So, we have the following three layers of LINQ, which work three-way:
• Identification of the data source
• Formalization of the query
• Execution of the query


Conclusion:

In this introductory article, we have discuss different aspects of LINQ. Currently, there are different flavors of LINQ for distinct data sources:
• SQL Server databases
• XML documents
• DataSet objects
• Managed collections

The LINQ engine is extensible so we can expect the third party vendors like Oracle to soon provide LINQ interfaces on top of their own products and data sources.