Language Integrated Query (LINQ) provides .NET developers some new and exciting features to query and manipulate data in a consistent and uniform way. It enables them to work with different type of data sources such as Arrays, collection of objects, XML documents, a relational databases, Active Directory or even Microsoft Excel sheets by writing or embedding queries in C# or Visual Basic language.
Thank you for reading this post, don't forget to subscribe!Microsoft has introduced many new keywords and features in both C# and Visual Basic languages to integrate LINQ technology. Microsoft has also added new namespaces in .NET Framework Library that contains new interfaces and hundreds of extension methods also called LINQ query operators. These methods perform different operations on different type of data sources in LINQ.
LINQ stands for Language-Integrated Query. Basically LINQ address the current database development model in the context of Object Oriented Programming Model. If some one wants to develop database application on .Net platform the very simple approach he uses ADO.Net. ADO.Net is serving as middle ware in application and provides complete object oriented wrapper around the database SQL.So developer must have good knowledge of object oriented concept as well as SQL to develop an application. But incase of Linq SQL statements are become part of the C# and VB.Net code so there are less chance of mistake.
LINQ enables developers to query data sources using a query like syntax with both C# and VB.NET. Using LINQ we can query any database and collection.
LINQ Flavors
-
LINQ to Objects
It provides the facility to query any kind of C# in-memory objects, like as arrays, lists, generic list and other collection types.LINQ to object query returns IEnumerable collection. It provides a new approach to query collection with powerful filtering, ordering and grouping capablities with minimum code.
-
LINQ to Ado.Net
LINQ to ADO.NET includes different flavors of LINQ to query data from different databases like as Microsoft SQL Server, Oracle, and others. It has following flavours
-
LINQ to SQL
It is specifically designed for working with Sql Server database. It provides run-time infrastructure for managing relational data as objects. It also supports transactions, views and stored procedures. It is an object-relational mapping (ORM) framework that allow 1-1 mapping of Sql Server database to .net classes. In this mapping the classes that match the database table are created automatically from the database itself and we can use these classes immediately.
-
LINQ to DataSet
It is an easy and faster way to query data cached in a DataSet object. It also allow LINQ to query over any database that can be query with Ado.Net.
-
LINQ to Entities
In many ways it is very similar to LINQ to SQL. It uses a conceptual Entity Data Model (EDM). The ADO.NET Entity Framework has been improved in .NET framework 4.0 to query any database like Sql Server, Oracle, MySql, DB2 and many more.
-
-
LINQ to XML
It provides an improved XML programming interface. Using this we can query, modify xml document and also save document after modification. System.Xml.Linq namespace contains classes for LINQ to XML.
-
PLINQ (Parallel LINQ)
PLINQ was introduced in .Net framework 4.0. It extends LINQ to Objects with a new parallel programming library. Using this, we can break/split up a query to execute simultaneously/parallel on different processors.
Current Data Access
On the .NET platform we have been and still are utilizing ADO.NET
for accessing different data sources. The open source community has also provided
the developers with a number of alternatives.
Language Integrated Query is the new addition to the .NET
family and as the name suggests it’s the kind of query style data access which
is fully supported by the language to effectively unify the way we access data
and to make our lives easier. LINQ is able to target a number of different sources namely Oracle,
MSSQL, XML and a few others, but for now we will focus on the most basic of
all, LINQ to Objects.
LINQ to Objects
Normally, to process and refine the data within our lists
and various other data structures, we have used either the ‘foreach’ loop or another
type of looping method to iterate through the objects and process them one by
one according to some condition. This is fine, but frankly it requires a lot of
basic coding that we all wish we didn’t have to write. Essentially we’ve had to tell the
compiler every single detail of the process in order to manipulate the data.
This is exactly where LINQ shines best. What LINQ allows us
to do is to simply tell the compiler what we’d like to perform and let the compiler work
out the best way to actually achieve that. If you’ve used SQL syntax before, the massive resemblances
between LINQ and any dialects of SQL will be the first thing that you’ll notice.
Like SQL, LINQ too supports the “select”, “from”, “where”, “join”, “group by”
and “order by” keywords. Here is a simple example of querying a list of objects:
List initialization:
List<Car> ListOfCars = new List<Car>()
{
new Car {name = “Toyota” , owner = “Alex” , model = 1992},
new Car {name = “Mitsubishi”, owner = “Jeff” , model = 2005},
new Car {name = “Land Rover”, owner = “Danny”, model = 2001},
new Car {name = “BMW” , owner = “Danny”, model = 2006},
new Car {name = “Subaru” , owner = “Smith”, model = 2003}
};
The query:
IEnumerable<Car> QueryResult = from car in ListOfCars
select car;
The first part of the preceding code simply populates a list
with four instance of the ‘Car’ class. The next part of the code, however, uses the
“from” and “select” keywords to select a group of objects. The main difference
between SQL and LINQ is that the “from” keyword comes before the “select”
keyword because we must first define the object we want to operate on. Finally
the “select” clause tells the compiler what we wish to extract in this query. The above
code simply extracts everything that is in the list and assigns it to the “QueryResult”
variable.
When we query things from objects (LINQ to Objects) our
queries always return an “IEnumrable<T>” list of objects. Essentially the
“IEnumerable” type is the kind of list that exposes the enumerator, which
supports a simple iteration over a non-generic collection, and <T>
is the type of each entry in the list.
Don’t worry if you aren’t familiar with “enumerators” and “generics”. Just
remember that the result of LINQ queries is always a collection like data
structure which allows for iterating through it using a loop like shown
bellow:
foreach(Car car in QueryResult)
Console.WriteLine(car.name);
We learned that LINQ always returns a collection structure similar
to any other lists. However, the LINQ query does not execute until its result is
accessed by some other piece of code, like the “foreach” loop above. This is to
allow us to continuously define the query without the overhead by re-evaluating
each new step in the query.
Projections
So far so good; but most of the time, our queries will need
to be more complex; so let’s try projecting data. In SQL, Projection means selecting
the name of the column(s) of table(s) which one wishes to see appearing in the result
of the query. In the case of LINQ to Objects, performing Projection will result
in a different query result type than the type of object that we perform the
query on.
There are two kinds of Projections that we can do. We can
either perform a Projection based on an existing object type, or go completely
the other way by using anonymous types. The following example is of the first
kind:
IEnumerable<CarOwner> QueryResult = from car in ListOfCars
select new CarOwner { owner_name = car.owner };
In the preceding code, the type of the query result is declared as
<CarOwner>, which is different to <Car>, the type that ‘ListOfCar’ variable is initialized with. We have
also used the “new” keyword and have done some assignments inside the curly
brackets. In the above code, using “select” with the “new” keyword tells the
compiler to instantiate a new ‘CarOwner’ object for every entry in the query result.
Also by assigning values to the new type we have initialized each instance
of the ‘CarOwner’ class.
Nonetheless, if you don’t already have a type defined to
use, you can still perform projections using anonymous types.
Projections using Anonymous Types
It would be a big hassle if, for every Projection, you were
forced to create a new type. That is why, as of C# 3.0, support for Anonymous
types was added to the language. An Anonymous type is declared using the “var”
keyword. It tells the compiler that the type of the variable is unknown until
it’s assigned for the first time.
var QueryResult = from car in ListOfCars
select new {
car_name = car.name,
owner_name = car.owner
};
foreach(var entry in QueryResult)
Console.WriteLine(entry.car_name);
The above is an example of performing a query with Anonymous
types. The only catch to look out for is that the compiler will not
allow returning Anonymous types from methods.
Accessing the properties of an Anonymous type is easy. In Visual Studio 2008, the Code
Completion/Intellisense also lists the properties exposed by the Anonymous type.

Refining Data
Usually as part of the LINQ query, we also need to refine the
query result by specifying a condition. Just like SQL, LINQ too uses the “where”
clause to tell the compiler what conditions are acceptable.
IEnumerable<Car> QueryResult = from car in ListOfCars
where car.name == “Subaru”
select car;
The preceding code demonstrate the use of the “where” clause and
the condition to follow. To further to define multiple conditions, LINQ supports
the ‘and’ (&&) and ‘or’ (||) constructs. The “where” part of the query has to always be a
Boolean expression, otherwise the compiler will complain.
Order By
When querying objects, it’s possible to rely on the query
target being already sorted. If that isn’t the case, LINQ can take care of that
by using the “order by” clause which will ensure the result of your query is
properly sorted.
IEnumerable<Car> QueryResult = from car in ListOfCars
orderby car.model
select car;
If you run the above code, you’ll see that the result of the
query is sorted in ascending order. You can alter the order by using the “ascending” and “descending”
keywords, and further change the order by specifying more than one field to sort
by. The following code shows how:
IEnumerable<Car> QueryResult = from car in ListOfCars
orderby car.model descending
select car;
Grouping
LINQ also allows grouping the query result by the value of a
specific property as shown in this example:
var QueryResult = from car in ListOfCars
group car by car.owner into carOwnersGroup
select carOwnersGroup.Key;
As you can see, LINQ supports the “group by” clause to
specify what object and by what property to group by. The “into” keyword will
then allow us to project on a grouping result which can be accessed by the “Key”
property.
Joins
LINQ supports joining data from different collections into one
query result. You can do this using the “join” keyword to specify what objects
to join and use the “on” keyword to specify the matching relationship between
the two objects.
Initializing related list:
List<Car> ListOfCars = new List<Car>()
{
new Car {name = “Mitsubishi”, owner = “Jeff” , model = 2005},
new Car {name = “Land Rover”, owner = “Danny”, model = 2001},
new Car {name = “Subaru” , owner = “Smith”, model = 2003},
new Car {name = “Toyota” , owner = “Alex” , model = 1992},
new Car {name = “BMW” , owner = “Danny”, model = 2006},
};
List<CarOwner> ListOfCarOwners = new List<CarOwner>()
{
new CarOwner {owner_name = “Danny”, age = 22},
new CarOwner {owner_name = “Jeff” , age = 35},
new CarOwner {owner_name = “Smith”, age = 19},
new CarOwner {owner_name = “Alex” , age = 40}
};
Query:
var QueryResult = from car in ListOfCars
join carowner in ListOfCarOwners on car.owner equals carowner.owner_name
select new {name = car.name, owner = car.owner, owner_age = carowner.age};
In the above code, using an Anonymous type, we have joined
the two objects in a single query result.
Object Hierarchies using Group Joins
So far, we’ve learned how we can use LINQ to build a flat
list query result. With LINQ, it’s also possible to achieve a hierarchical query
result using “GroupJoin”. In simple words, we could assign objects to
properties of every entry with LINQ query.
List<Car> ListOfCars = new List<Car>()
{
new Car {name = “Mitsubishi”, owner = “Jeff” , model = 2005},
new Car {name = “Land Rover”, owner = “Danny”, model = 2001},
new Car {name = “Subaru” , owner = “Smith”, model = 2003},
new Car {name = “Toyota” , owner = “Alex” , model = 1992},
new Car {name = “BMW” , owner = “Danny”, model = 2006},
};
List<CarOwner> ListOfCarOwners = new List<CarOwner>()
{
new CarOwner {owner_name = “Danny”, age = 22},
new CarOwner {owner_name = “Jeff” , age = 35},
new CarOwner {owner_name = “Smith”, age = 19},
new CarOwner {owner_name = “Alex” , age = 40}
};
var QueryResult = from carowner in ListOfCarOwners
join car in ListOfCars on carowner.owner_name equals car.owner into carsGroup
select new {name = carowner.owner_name, cars = carsGroup};
foreach(var carOwner in QueryResult)
foreach(var car in carOwner.cars)
Console.WriteLine(“Owner name: {0}, car name: {1}, car model: {2}”, carOwner.name, car.name, car.model);
In the above example, the “Join” clause is followed by an “into”
part. This differs to the previous join operation that we looked at. Here, the “into”
clause is used to group cars by the owner (into carsGroup) and assign the grouping to the
“cars” property of the anonymous type.
Standard Query Operators
Thus far, everything that we’ve seen has been supported by the C# 3.0
syntax. However, there is still a large number of operations that C# 3.0 does not
support. The standard query operators provide query capabilities including
filtering, projection, aggregation, sorting and more. These operations are therefore supported
as methods of the LINQ library and can be executed on result of a query like shown in the
following screenshot:

These operators are listed below for your reference.
Aggregate Operators
- Sum: returns the sum of all entries
- Max: returns the entry with the maximum value
- Min: returns the entry with the minimum value
- Average: returns the average value for the collection
- Aggregate: used for creating a customized aggregation
- LongCount: when dealing with a large collection, this method will return a value up to the largest value supported by the “long” class
- Count: returns an “integer” for the count of items in the collection
Element Operators
- First: returns the first entry from the result collection
- FirstOrDefault: if empty collection, will return the default value, otherwise will return the first entry from the collection
- Single: will return only element from the collection
- SingleOrDefault: if empty collection, will return the default value, otherwise will return only element from the collection
- Last: returns the last entry from collection
- LastOrDefault: if empty collection, will return the default value, otherwise returns the last entry from collection
- ElementAt: returns the element at the specified position
- ElementAtOrDefault: if empty collection, will return the default value, otherwise returns the element at the specified position
Set Related Operators
- Except: similar to the left join in SQL, will return entries from the one set that doesn’t exist in another set
- Union: returns all entries from both objects
- Intersect: returns the same elements from either sets
- Distinct: returns unique entries from the collection
Generation Operators
- DefaultIfEmpty: if result is empty, returns default value
- Repeat: repeats on returning objects for specified number of times
- Empty: will return an empty IEnumerable collection
- Range: returns a range of numbers for a specified starting number and count
Refining Operators
- Where: will return objects that meet the specified condition
- OfType: will return objects of the specified type
Conversion Operators
- ToLookup: returns the result as a lookup
- ToList: returns the result as a List collection
- ToDictionary: returns the result as a dictionary
- ToArray: returns the result as an Array collection
- AsQueryable: returns the result as a IQueryable<T>
- AsEnumerable: returns the result as a IEnumerable<T>
- OfType: filters the collection according to the specified type
- Cast: used to convert a weakly typed collection into a strongly typed collection
Partitioning Operators
- Take: returns a specified number of records
- Takewhile: returns a specified number of records while the specified condition evaluates to true
- Skip: skips specified number of entries and returns the rest
- SkipWhile: skips specified number of entries while the specified condition evaluates to true
Quantifier Operators
- Any: returns true or false for a specified condition
- Contains: returns true or false for existence of the specified object
- All: returns true or false to all objects meeting the specified condition
Join Operators
- Join: returns entries where keys in sets are the same
- GroupJoin: used to build hierarchical objects based on a master and detail relationship
Equality Operators
- SequenceEqual: returns true when collections are equal
Sorting Operators
- Reverse: returns a reversed collection
- ThenBy: used to perform further sorting
- ThenByDescending: used to perform further sorting in descending order
- OrderBy: used to define order
- OrderByDescending: used to define descending order
Projection Operators
- SelectMany: used to flatten a hierarchical collection
- Select: used to identify the properties to return
Concatenation Operators
- Concat: used to concatenate two collections