Language Integrated Query (LINQ)

LINQ extends the language by the addition of query expressions, which are similar character to SQL statements and can be used to conveniently extract and process data from arrays, enumerable classes, XML documents, relational databases and third-party data sources. 

SQL is a Structured Query Language used to save and retrieve data from a database. In the same way, LINQ is a structured query syntax built in C# and VB.NET to retrieve data from different types of data sources such as collections, ADO.Net DataSet, XML Docs, web service and MS SQL Server and other databases.

LINQ queries return results as objects. It enables you to uses object-oriented approach on the result set and not to worry about transforming different formats of results into objects.

Advantages of LINQ
Familiar language: Developers don’t have to learn a new query language for each type of data source or data format.
Less coding: It reduces the amount of code to be written as compared with a more traditional approach.
Readable code: LINQ makes the code more readable so other developers can easily understand and maintain it.
Standardized way of querying multiple data sources: The same LINQ syntax can be used to query multiple data sources.
Compile time safety of queries: It provides type checking of objects at compile time.
IntelliSense Support: LINQ provides IntelliSense for generic collections.
Shaping data: You can retrieve data in different shapes.

We can write LINQ queries for the classes that implement IEnumerable<T> or IQueryable<T> interface.
The Enumerable and Queryable are two static classes that contain extension methods to write LINQ queries.
Enumerable :-
The Enumerable class includes extension methods for the classes that implement IEnumerable<T> interface. 
IEnumerable<T> type of collections are in-memory collection like List, Dictionary, SortedList, Queue, HashSet, LinkedList.
Queryable :-
The Queryable class includes extension methods for classes that implement IQueryable<t> interface.
The IQueryable<T> interface is used to provide querying capabilities against a specific data source where the type of the data is known.
The static Queryable class includes extension methods for classes that implements the IQueryable<T> interface.

There are APIs available to access third party data; for example, LINQ to Amazon provides the ability to use LINQ with Amazon web services to search for books and other items. This can be achieved by implementing the IQueryable interface for Amazon.

C# 3.0(.NET 3.5) introduced the lambda expression along with LINQ. The lambda expression is a shorter way of representing anonymous method using some special syntax.
Example for Lambda Expression in C# :- 
s  =>  s.Age > 12  &&  s.Age < 20




Standard Query Operators in LINQ :- 

Standard Query Operators in LINQ are actually extension methods for the IEnumerable<T> and IQueryable<T> types. They are defined in the System.Linq.Enumerable and System.Linq.Queryable classes. Standard Query Operators can be classified based on the functionality they provide. 

The following are the classification of Standard Query Operators:-

Classification  |  Standard Query Operators
Filtering-         Where, OfType
Sorting-         OrderBy, OrderByDescending, ThenBy, ThenByDescending, Reverse
Grouping- GroupBy, ToLookup
Join- GroupJoin, Join
Projection- Select, SelectMany
Aggregation- Aggregate, Average, Count, LongCount, Max, Min, Sum
Quantifiers- All, Any, Contains
Elements- ElementAt, ElementAtOrDefault, First, FirstOrDefault, Last, LastOrDefault, Single,SingleOrDefault
Set-         Distinct, Except, Intersect, Union
Partitioning- Skip, SkipWhile, Take, TakeWhile
Concatenation-Concat
Equality-         SequenceEqual
Generation- DefaultEmpty, Empty, Range, Repeat
Conversion- AsEnumerable, AsQueryable, Cast, ToArray, ToDictionary, ToList


The following are the operators  available in LINQ :-

Where -         Returns values from the collection based on a predicate function.
OfType  -         Returns values from the collection based on a specified type. However, it will depend on their ability to cast to a specified type.
OrderBy - Sorts the elements in the collection based on specified fields in ascending or descending order.
OrderByDescending -Sorts the collection based on specified fields in descending order. Only valid in method syntax.
ThenBy  - Only valid in method syntax. Used for second level sorting in ascending order.
ThenByDescending-Only valid in method syntax. Used for second level sorting in descending order.
Reverse  - Only valid in method syntax. Sorts the collection in reverse order.
GroupBy - The GroupBy operator returns groups of elements based on some key value. Each group is represented by IGrouping<TKey, TElement> object.
ToLookup - ToLookup is the same as GroupBy; the only difference is the execution of GroupBy is deferred whereas ToLookup execution is immediate.
Join  -         The Join operator joins two sequences (collections) based on a key and returns a resulted sequence.
GroupJoin - The GroupJoin operator joins two sequences based on keys and returns groups of sequences. It is like Left Outer Join of SQL.
All -                 Checks if all the elements in a sequence satisfies the specified condition
Any -         Checks if any of the elements in a sequence satisfies the specified condition
Contains - Checks if the sequence contains a specific element
Aggregate - Performs a custom aggregation operation on the values in the collection.
Average - calculates the average of the numeric items in the collection.
Count -         Counts the elements in a collection.
LongCount - Counts the elements in a collection.
Max -         Finds the largest value in the collection.
Min -         Finds the smallest value in the collection.
Sum -         Calculates sum of the values in the collection.
ElementAt - Returns the element at a specified index in a collection
ElementAtOrDefault- Returns the element at a specified index in a collection or a default value if the index is out of range.
First -         Returns the first element of a collection, or the first element that satisfies a condition.
FirstOrDefault - Returns the first element of a collection, or the first element that satisfies a condition. Returns a default value if index is out of range.
Last -         Returns the last element of a collection, or the last element that satisfies a condition
LastOrDefault-Returns the last element of a collection, or the last element that satisfies a condition. Returns a default value if no such element exists.
Single -         Returns the only element of a collection, or the only element that satisfies a condition.
SingleOrDefault- Returns the only element of a collection, or the only element that satisfies a condition. Returns a default value if no such element exists or the collection does not contain exactly one element.
Last -         Returns the last element from a collection, or the last element that satisfies a condition
LastOrDefault-Returns the last element from a collection, or the last element that satisfies a condition. Returns a default value if no such element exists.
Single -         Returns the only element from a collection, or the only element that satisfies a condition. If Single() found no elements or more than one elements in the collection then throws InvalidOperationException.
SingleOrDefault-The same as Single, except that it returns a default value of a specified generic type, instead of throwing an exception if no element found for the specified condition. However, it will thrown InvalidOperationException if it found more than one element for the specified condition in the collection.
Empty -         Returns an empty collection
Range -         Generates collection of IEnumerable<T> type with specified number of elements with sequential values, starting from first element.
Repeat -         Generates a collection of IEnumerable<T> type with specified number of elements and each element contains same specified value.
Distinct -         Returns distinct values from a collection.
Except -         Returns the difference between two sequences, which means the elements of one collection that do not appear in the second collection.
Intersect -     Returns the intersection of two sequences, which means elements that appear in both the collections.
Union -         Returns unique elements from two sequences, which means unique elements that appear in either of the two sequences.
Skip -         Skips elements up to a specified position starting from the first element in a sequence.
SkipWhile - Skips elements based on a condition until an element does not satisfy the condition. If the first element itself doesn't satisfy the condition, it then skips 0 elements and returns all the elements in the sequence.
Take -         Takes elements up to a specified position starting from the first element in a sequence.
TakeWhile - Returns elements from the first element until an element does not satisfy the condition. If the first element itself doesn't satisfy the condition then returns an empty collection.
AsEnumerable-Returns the input sequence as IEnumerable<t>
AsQueryable - Converts IEnumerable to IQueryable, to simulate a remote query provider
Cast -         Coverts a non-generic collection to a generic collection (IEnumerable to IEnumerable<T>)
OfType -         Filters a collection based on a specified type
ToArray -         Converts a collection to an array
ToDictionary -  Puts elements into a Dictionary based on key selector function
ToList -         Converts collection to List
ToLookup - Groups elements into an Lookup<TKey,TElement>