Jun 19 2008

Linq compiled queries (1 of 2)

Published by Raja Nadar at 2:49 pm under c# 3.0, linq

I wanted to blog about Compiled queries in LINQ in this post. However, before doing that, I realized it would be good if I wrote something about the foundation on which the Compiled Query syntax is built.

This is because the call to a Compiled Linq Query involves calling the Compile() method:

public static Func<TArg0, TArg1, TResult> 
 
CompiledQuery.Compile<TArg0, TArg1,  TResult>
 
(Expression<Func<TArg0, TArg1, TResult>> query)
 
 where TArg0 : DataContext;

Now if the above syntax makes total sense to you, then you are probably over the following words. Else, you could read on to make sense of the above syntax.

Assume we have a delegate type defined as follows:

delegate int MyDelegateType(int a, int b)

this delegate can contain (thinking of code container) all methods which return ‘int’ and take 2 integer parameters.
E.g.

public int AddMethod(int a, int b)
 
MyDelegateType myDelegateObject = new MyDelegateType(AddMethod);

As you know, C# 2.0, simplifies this synax. we can now do:

MyDelegateType myDelegateObject = AddMethod;

looks good so far..

Now suppose, we make the delegate deal with generic types.

delegate T MyGenericDelegateType<T> (T a, T b)

this delegate can contain all methods which return ‘T’ type and take 2 T type parameters.

MyGenericDelegateType<int> myGenericDelegateObject = AddMethod;

Now, this is the AddMethod

public int AddMethod(int a, int b)
{
  return a + b;
}

As you know using C# 2.0 anonymous methods, we could write:

MyGenericDelegateType<int> myGenericDelegateObject =
delegate (int a, int b) { return a + b };

C# 3.0, further simplifies this anonymous method syntax, by eliminating even the delegate keyword, and getting the => operator. (Lambda Expressions coming in..)

Hence in C# 3.0, we can write:

MyGenericDelegateType<int> myGenericDelegateObject =
(int a, int b) => return a + b;

A further simplification to the above syntax is removing the types declared. This is because C# 3.0 is equipped with the type inference feature.

MyGenericDelegateType<int> myGenericDelegateObject = (a,b) => a + b;

Notice how we removed even the return keyword. This is perfectly valid, if the method contains only a single return statement.

Now the System.Linq namespace already defines some generic delegates for us. e.g. One of them is:

public delegate TResult Func<A0, A1, TResult> (A0 arg0, A1 arg1);

What this means is we don’t need to define our own delegate types, every time we want to use one with a similar signature.

we could directly say:

Func<int, int, int> myLinqDelegateObject = AddMethod;

Here TResult, A0 and A1 are int types. Replacing by lambda expressions,

Func<int, int, int> myLinqDelegateObject = (a,b) => a+b;

We can use this delegate object as

int sum = myLinqDelegateObject(3, 4);  // sum = 7;

Here myLinqDelegateObject is nothing but a delegate object (instance), of a delegate type already defined by the System.Linq namespace.

An Expression Tree is nothing but an object of type

System.Linq.Expressions.Expression<TDelegateType>

, where TDelegateType is the delegate the tree represents.

e.g.

Expression<Func<int, int, int>> myExpressionTreeObject = (a,b) => a+b;

Expression trees are nothing but an in memory representation of code. sort of a mini code segment, which can be evaluated later on demand, and can be built upon.

Based on all the points above, if we see the syntax now:

public static Func<TArg0, TArg1, TResult> 
 
CompiledQuery.Compile<TArg0, TArg1,  TResult>
 
(Expression<Func<TArg0, TArg1, TResult>> query)
 
 where TArg0 : DataContext;

It should look clear that, the Compile method takes in an Expression Tree object (query), of which the first parameter should be of type DataContext (Generic Contraint), and the return type is a Delegate object. Func

So the use of the Compile method would be as follows:

var queryDelegate =  CompiledQuery.Compile(
 
  (MyDataContext db, string param1, string param2) =>
 
  db.MyEntity
     .Where(v => v.Column1.Trim().ToLower() == param1.Trim().ToLower())
     .Where(v => v.Column2.Trim().ToLower() == param2.Trim().ToLower()));

Here queryDelegate is of type:

Func<MyDataContext, string, string, IQueryable<MyEntity>>

and can be used as follows:

var MyEnitities = queryDelegate(db, param1value, param2value);

As you can see, concise delegate syntax ( => ), generics (T), anonymous methods/types (var), type inference (var), lambda expressions (=>) etc, work under the hood for the Compile method. C# 3.0 is cool.

As for the exact use of Linq compiled queries, their advantages and disadvantages, I’ll be writing about it in part 2 of this post..

3 Responses to “Linq compiled queries (1 of 2)”

  1. [...] in my last post, I wrote about the Linq compiled queries syntax, before diving into its use. this post is about the [...]

  2. Gopikrishna Gopalon 11 Dec 2008 at 9:25 am

    Hi Raja,

    Your post on compiled queries was very interesting. I am fascinated by the way you have drafted the flow of content. It was very easy to understand. Great work.
    I am hoping to have a look at all of your posts, for I am sure of gettng more inputs.

    Regards,
    Gopi.

  3. Raja Nadaron 11 Dec 2008 at 9:32 am

    thanks for the words Gopi. my project has held me up a little, but you’ll see new posts soon.

Trackback URI | Comments RSS

Leave a Reply