Monday, October 7, 2013

Overview of LINQ (.NET Language-Integrated Query)

First of all LINQ is not a new thing and it was introduced with Visual Studio 2008 and in .NET Framework 3.5. If I am not mistaken the released date of LINQ was back in year 2007 and now it’s almost the end of 2013.

Still I wanted to write about LINQ because I have seen some confusions in some of my fellow developers and even in myself over LINQ. So this is kind of an effort to clearing things out for all who has confusions and of course to myself too.

This is basically an overview of LINQ, I might not be digging deep of all the things I am mentioning here, just trying to clear the picture as a whole.

Let’s start over with a brief yet important introduction to LINQ.

Language-Integrated Query or LINQ is simply some set of statements which can be integrated into following two programming languages which are Visual C# and Visual Basic (LINQ does not directly support Java nor C++, but there are some implementations filling the language gap). So the language syntax of C# and Visual Basic are extended to query and update data, almost in any kind of data source.

Let’s take SQL as a simple example. Some of your queries to manipulate data in Microsoft SQL Server are different from the queries you write against Oracle. The beauty of LINQ is no matter what your data source, you keep writing your queries using the same syntax's.

Another most important thing is, If I take SQL query as an example, the query is expressed as simple strings. The Visual Studio does not support metadata (table names etc) and therefore there is no IntelliSense. There is no compile-time syntax checking because it is just a set of strings. But with LINQ you will get everything. Rich metadata is supported with IntelliSense, compile-time syntax checking is there and provides static typing to your result.

So as I have mentioned before LINQ can be used against almost any kind of data source which can be categorized as follows.
  1. LINQ to ADO.NET
    • LINQ to DataSet
    • LINQ to SQL
    • LINQ to Entities
  2. LINQ to XML
  3. LINQ to Objects

LINQ to ADO.NET

LINQ to ADO.NET enables you to query over any enumerable object in ADO.NET. And this can be further categorized into LINQ to DataSet, LINQ to SQL and LINQ to Entities.
LINQ to DataSet
LINQ to DataSet makes it easier and faster to query over data cached in a DataSet object. As you may already know DataSet is the key element is ADO.NET disconnected architecture. The advantage of LINQ to DataSet is we can write queries using the programming language (C#/Visual Basic) and not using the SQL.
LINQ to SQL
In LINQ to SQL, the data model of a relational database is mapped to an object model expressed in the programming language. When executing queries LINQ to SQL, the LINQ query is transformed into SQL and executes in the database. When the query returns values LINQ to SQL transformed the result set into objects that we have used in the object model.
LINQ to Entities
LINQ to Entities provides writing LINQ queries against the Entity Framework model using C#/Visual Basic. Queries against the Entity Framework are represented by command tree queries (A query command tree is an object model representation of a query) which executes against the object context. LINQ to Entities converts LINQ queries to command tree queries, executes the queries against the Entity Framework, and returns objects that can be used by both the Entity Framework and LINQ.

LINQ to XML

LINQ to XML is a LINQ-enabled, in-memory XML programming interface that enables you to work with XML from within the .NET Framework programming languages.

LINQ to XML brings the XML document into memory. You can query and modify the document, and after you modify it, you can save it to a file or serialize it and send it over the Internet.

LINQ to Objects

LINQ to Objects refers to the use of LINQ queries with any IEnumerable or IEnumerable<T> (sometimes back I wrote this post about IEnumerable<T> and IQueryable<T>, it might help you understanding IEnumerable and IEnumerable<T>) collection directly, without the use of an intermediate LINQ provider or API such as LINQ to SQL or LINQ to XML.

At last it’s the end of the theory part. Now let’s have a look at LINQ in action. To demonstrate some action I am going to use LINQ to Objects here.

I am creating a console application and I have following two classes “Employee” and “Department” and some two helper methods returning values.
public class Department
{
    public int DepartmentId { get; set; }
    public string DepartmentDesc { get; set; }
 
    public static List<Department> GetDepartments()
    {
        return new List<Department>() 
        {
            new Department() 
            { 
                DepartmentId = 1, 
                DepartmentDesc = "Microsoft Visual Studio"
            },
            new Department() 
            { 
                DepartmentId = 2, 
                DepartmentDesc = "Microsoft SQL Server"
            }
        };
    }
}
 
public class Employee
{
    public int EmployeeId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int DepartmentId { get; set; }
 
    public static List<Employee> GetEmployees()
    {
        return new List<Employee>() 
        {
            new Employee() 
            { 
                EmployeeId = 1, 
                FirstName = "Jaliya", 
                LastName = "Udagedara", 
                DepartmentId = 1
            },
            new Employee() 
            { 
                EmployeeId = 2, 
                FirstName = "John", 
                LastName = "Smith", 
                DepartmentId = 2
            },
            new Employee() 
            { 
                EmployeeId = 3, 
                FirstName = "Jane", 
                LastName = "Smith", 
                DepartmentId = 1
            }
        };
    }
}

Now in the Main method I am going to use LINQ to query these collections. A thing to note is when writing LINQ queries, there are two ways you can write them. Once is the Query Syntax and the other is Method Syntax.

First let’s have a quick look at both Query Syntax and Method Syntax.

Query Syntax and Method Syntax

Query syntax and Method syntax are semantically identical, but many people find Query syntax simpler and easier to read. When the LINQ query is written using Query syntax and when the application get compiled, The Query syntax will be transformed back into Method syntax. And those method calls will be sent to CLR. The one significant different between these two is, when using Method syntax, there will be a heavy use in Lamba expressions. I believe you have some knowledge in Lambda expressions here, because otherwise you will not be able to understand what happens in LINQ using Method syntax.

Now I am going to write some LINQ queries and I will be writing using both these ways.

I have following two collections.
List<Employee> employees = Employee.GetEmployees();
List<Department> departments = Department.GetDepartments();

Let’s say I want to select all the employees where the LastName is “Smith”.
IEnumerable<Employee> query = from e in employees
                              where e.LastName == "Smith"
                              select e;
IEnumerable<Employee> query = employees
                                .Where(e => e.LastName == "Smith");
Now let’s have a look at what’s happening here. My LINQ query is against the List of type Employee which is employees. And it’s returning me an IEnumerable of type Employee. When writing the query Visual fully supports IntelliSense, suggesting me the properties which the “Employee” has.

Deferred Execution and Immediate Execution

There is something important thing to note here. If you debug the code and examine the value of queries, you will see something like this.
image
Result View
For the Results View, you can see a message saying “Expanding the Results View will enumerate the IEnumerable”. What does this mean?. Actually this is called the deferred execution. The query variable itself only stores the query commands. The actual execution of the query is postponed until you iterate over the query variable in a foreach statement. But let’s say you want to immediately execute the query. For that you can write the query in the following way.
IEnumerable<Employee> query = (from e in employees
                                where e.LastName == "Smith"
                                select e).ToList();
IEnumerable<Employee> query = employees
                    .Where(e => e.LastName == "Smith").ToList();

Now if you debug and examine the result set, this is what you will see.
image
Result
Here to force immediate execution of any query and cache its results, you can call the ToList<TSource> or ToArray<TSource> etc. methods.

Data Transformation with LINQ

Now let’s have a look at another example which will demonstrate table join and one of the most powerful feature of LINQ queries which is the ability to create new types. This is accomplished in the select clause.

Let’s say I want write a query to get the Employees First Name, Last Name and the Description of Department where he is working on.
var query = from e in employees
            join d in departments 
            on e.DepartmentId equals d.DepartmentId
            select new 
            { 
                FName = e.FirstName, 
                LName = e.LastName, 
                DDesc = d.DepartmentDesc 
            };
var query = employees
            .Join(departments,
            d => d.DepartmentId,
            e => e.DepartmentId,
            (e, d) => new
            {
                FName = e.FirstName,
                LName = e.LastName,
                DDesc = d.DepartmentDesc
            });

This shows another nice feature in LINQ which is the ability to transform data (creating new types etc.). You can use select new object initializer with either a named object or an anonymous type. Here I am creating a anonymous type and I have used var as the type of the query, because the select statement returns an anonymous type.

So that's it. Hope you would find something interesting from the post. I am uploading the demo app to my SkyDrive.


Happy Coding.

Regards,
Jaliya

1 comment: