.NET Language Integrated Query (LINQ)

As of C# 3.0 we have had a standard way of querying data through Language Integrated Query or LINQ for short. C# 3.0 introduces its query language as a first-class citizen. The querying are type checked by the C# compiler. C# 3.0 also introduced things like lamda expressions and extension methods et. al. Both of which are crucial to LINQ. In a LINQ query there are lamda expressions. These are usually a smaller anonymous method code-squirted in place for an expected LINQ delegate.

In LINQ there are three types of delegates. They are:

  • Func

Defines a method that optionally takes a set of parameters, performs some action, and returns a value.

  • Action

Defines a method that takes a set of parameters, performs some action, and has no return value.

  • Predicate

Defines a method that takes one parameter and returns a boolean value.

LINQ operates on IEnumerable<T> and IQueryable<T>. IQueryable<T> inherits from IEnumerable<T>.

The IEnumerable<T> is used to navigate a read-only collection of managed objects. It is used to iterate from one object to the next, from start of collection to end of collection in forward direction only.

The IQueryable<T> functions by creating an expression tree from the input query. A custom LINQ provider is used to convert this expression tree into some query that some other entity like i.e. a web-service can understand. This way LINQ can work against any data source, given you have a LINQ provider for it.

The following is a list of some LINQ providers:

  • LINQ to Active Directory
  • LINQ to Amazon
  • LINQ to CRM
  • LINQ to Excel
  • LINQ to Flickr
  • LINQ to Google
  • LINQ to Indexes
  • LINQ to IQueryable
  • LINQ to JavaScript
  • LINQ to JSON
  • LINQ to LDAP
  • LINQ to Lucene
  • LINQ to Metaweb
  • LINQ to MySQL
  • LINQ to NHibernate
  • LINQ to Parallel (PLINQ)
  • LINQ to RDF Files
  • LINQ to Sharepoint

Here is a simple example of a LINQ query. Notice the two ways of writing the query. One native to C# (QuerySyntax) and the other native to .NET using extension methods:

int[] numbers = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var gtFiveQuerySyntax = from num in numbers where num > 5 select num;
var gtFiveExtensionSyntax = numbers.Where( n => n > 5 );

The numbers array implements IEnumerable<int>. So the Where extension method operates on an IEnumerable<int>. The Where extension method takes one Func delegate. That is an anonymous method lamda expression that returns true if the number is larger than 5. The result from this LINQ query is a new IEnumerable<int> that contains the numbers 6 through 9. We can also write more complicated queries. This example adds an orderby part. Notice we are chaining the .NET extension methods:

int[] numbers = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var gtFiveQuerySyntax = from num in numbers where num > 5 orderby num descending select 

The outcome is that gtFiveXSyntax is an IEnumerable<int> with the result 9 through 6. Reverse order from before.

The Where and OrderByDescending are examples of extension methods defined in the type Enumerable from the assembly System.Code.dll.

Here is a list of some common extension methods.

OperatorPurposeDeferred
AggregateAggregateNo
AllQuantifiersNo
AnyQuantifiersNo
AverageAggregateNo
CastConversionYes
FirstElementNo
GroupByGroupingYes
LongCountAggregateNo
MaxAggregateNo
MinAggregateNo
SelectProjectionYes
SkipPartitioningYes
SumAggregateNo
TakePartitioningYes
TakeWhilePartitioningYes
ThenByOrderingYes
ThenByDescendingOrderingYes
ToArrayConvertionNo
ToListConvertionNo
WhereRestrictionYes

There are two different types of LINQ extension methods. Non-deferred and deferred. A deferred extension method is easy to spot. It returns an IEnumerable<T> or IOrderedEnumerable<T>. A deferred extension method is an extension that yields an item when enumerated. A non-deferred extension method however have already enumerated all its items before returning. Extension methods of IQueryable<T> are located in the Queryable type in System.Code.dll.

There are some handy rules regarding  parenthesis, brackets and semicolon when one writes lamda expressions in C#. They are:

  • When you have only one lamda argument

No need for parenthesis around argument m.

list.Where( m => m.Age < 100 );

Here m is argument, and as you can see there is no need for parenthesis.

  • When you have multiple arguments in lamda expression there has to be parenthesis.

list.Where( (m, q) => m.Age == q.TargetAge );

Here m and q are arguments, and as you can see they must be in parenthesis.

  • When one only uses one statement in lamda expression, there is no need for brackets and semicolon. Se above. But if there are more than one statement you need both parenthesis, semicolon and brackets.
list.Where( (m,q) => 
{
	int sub_age = 0;
	if ( m.Age > q.TargetAge )
	{
sub_age = 20;
}
return (m.Age-sub-age) > q.TargetAge;
 	};

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: