Archive for February 2013
When writing database scripts, we prefer stored procedures over regular Sql statements for a couple of reasons. Stored procedures are precompiled, so they avoid the query compile time; on a network, passing a short string to invoke a stored procedure reduces a huge network traffic if the stored procedure had number of lines of code, and if we were using Sql statements instead of stored procedures. Other benefits are there too.
When using ORMs like LINQ to SQL, or ADO.NET Entity Framework where the Sql queries are dynamically created for you on the fly, those Sql statements have to be compiled by the Sql server every time a query is issued. And before the query is issued to the SQL server, LINQ has to parse the expression tree and spew out the SQL, which happens almost every time. In order to reduce the process of walking through the expression tree and constructing a SQL statements every time, they could be cached. To enable caching of a query, the ORMs offer a feature called compiled queries, so when we have a situation where we iterate over a query over and over again, it could be compiled and kept to improve performance.
Let’s take a look at how easy it is to write them and how to make them globally available. [The recent version Entity Framework 5.0 released with .Net framework 4.5 has compiled queries feature on by default – http://stackoverflow.com/questions/7337027/ef-4-2-impact-of-auto-compiled-linq-queries]
Below code shows you how you would normally define a DataContext and query a table.
If we wanted this query to be parsed at compile time and translated to SQL statements, so LINQ to SQL or Entity Framework does not have to dynamically build the SQL query every time a query like this is executed, then we should make it a compiled query to improve performance.
The Compile method of the CompiledQuery class accepts a Func delegate with template parameters and returns a Func delegate. At the basis, what we always should know about the Compile method is, we can pass in up to 15 input parameters, and take one output parameter. If you see the query above, we are using the NorthwindDataContext variable named nwc, that we are using in our LINQ query. And the entire LINQ query returns an IQueryable of Anonymous type for us.
Below is a sample of making the same query available in a compiled form local to a method. We call the Compile method with a NorthwindDataContext as a parameter and the entire anonymous delegate (the method inside the compile method) returns an IQueryable of the an Anomynous type derived from the customer.
When we want to call the compiled query, we pass in a datacontext nwc and the rest of the code is same.
This is good, most developers tend to have all the SQL queries in one cs file and refer it from there. If you follow that approach for compiled queries, and make then static instead, then the queries would be compiled once during the static variable initialization, and stays compiled untill the application’s lifetime yielding a significant boost in performance.
To demonstrate that, I am going to slightly modify the LINQ query to accept one more string paramter named country. Now the regular LINQ query we have looks like below
Nothing’s changed, except that we are passing a new string parameter named country along with the NorthwindDataContext. Remember when I said the entire result of the LINQ query is an IQueryable of the returned type. In this case the type that is returned is Customer, so it is IQueryable<Customer>. And the input parameters are NorthwindDataContext and a string. If that is clear, then what gets actually returned from the CompiledQuery.Compile method is a Func delegate. And that Func delegate in our case here, is going to accept two input parameters – one the NorthwindDataContext object, another a string; it’s output is IQueryable<Customer>.
When it was local, we used a var keyword and the type was automatically inferred to us. Now when we are talking about making a compiled query as a static member variable of a class, we don’t really have an option to use the var keyword, but to specify the exact type.
So, how would you define a Func delgate that takes NorthwindDataContext and string as input parameters, and returns an IQueryable<Customer> as an output parameter?
Func<NorthwindDataContext, string, IQueryable<Customer>>
Create the above static variable in a class named CompiledQueries, then you can access it, just like we did before, but we gain performance.
Download the complete source code – https://renouncedthoughts.files.wordpress.com/2013/02/linqtosqlcompiledqueries1.doc
The word document contains embedded zip file with the original Visual Studio solution.
I thought of naming this post “Evolution of lambdas in C#”, then I decided that wouldn’t be closest appropriate name for the example that I wanted to discuss. The key to understand a lambda in C# is to understand a delegate. Besides the overly blatant blather – “delegates are nothing but function pointers”, I am going to assert that delegates in C# are very similar to function pointers in C or C++ ;). What did I say? OK!
Let’s get one thing straight, think about the paradigm of passing arguments to a method. A method with a parameter named int i, would allow you to pass any argument like 1, 2, 3, 4, 5, 6, 7, 8, …32767…2147483647.
So we sort of seem to get a flexibility there (basis of why we wanted a method in programming – reuse, and possibly call it with different arguments), instead of a method that takes a fixed argument, we have a flexibility to pass in a whole range of values. int is a data type. i is the parameter name, those numbers above are arguments. Very easy concept that any programmer under the sun wouldn’t even dare to defy. In case he did, we would all think he’s crazy, or he lost his brains somewhere towards obsession of trying to defy otherwise. Hey, easy, no arguments about the arguments there!
So somehow, we started writing methods to do repetitive actions. And then “fathers of computer programming” thought of passing a method itself as a argument to a method (a method with a parameter, that accepted a certain type of function – just like the way the data type int allowed us to pass 1, 2, 3, 4,….). But we had to do something extra to pass a function as an argument (we will have to define what our delegate is). int had a whole range of values defined – those numbers above. so we did not really have to re-define what an a int really was. For all we know is int is a datatype defined by the language that accepts certain values as arguments.
Well, in case of delegates, we are free to choose the arguments (or the possible set of values that a delegate type can accept). For instance, lets define a delegate in pseudo-code
so we defined a delegate!
delegate is a type, just as how int a is a type. We already know that int accepts the numbers above and it constrains itself to the boundaries of those numbers i.e, from 0 to 2147483647, considering signed integer, because the language/compiler writers programmed it that way. Now, the delegate DoSomeMath is capable of accepting any method that takes two int as input and returns an int as output; it constrains itself to any method that takes two int as input and returns an int as output.
What this means is, we can have methods like below, and they all qualify to be the accepted by the delegate type named DoSomeMath .
To summarize, delegate is a type, DoSomeMath is the name of the delegate, all the Add, Sub, Mul, Div methods would qualify to be the arguments of a parameter named math below
Now, that we know how to declare a delegate, and pass a method to it, what’s the point if don’t invoke the method that was passed as an argument? Now, stay with me as I will show you an example of how you could invoke a delegate. Well, you know enough is enough, I tried by best to get a grip on delegates, and that’s how I understood it.
Remember the steps involved,
Create a delegate type
Create methods matching the delegate
Finally, invoke the delegate
What I have seem to have grasped, is that the step 2, was some sort of overhead for developers and Microsoft in it’s C# compiler added anonymous delegates, and later lambda expressions to save some development time by introducing a new syntax – in the industrial parlance, syntax sugar as they call it.
C# delegate syntax
Let’s dive in to C#, and try creating a delegate that seems to incorporate a common real time need. I want to write a little method named PrintAllFiles and make it accept a directory location, and a filter condition. The parameter named condition is special here, because it is delegate type. Lets create that.
The FileFilterDelegate is capable of accepting any method that accepts a FileInfo object and returns a bool. So the two methods below qualify to be our arguments since they both accept a FileInfo parameter and return a bool.
Now, lets write the PrintAllFiles method
Alright, where am I calling the delegate? it is right inside the if condition. item is of the type FileInfo, then I call the method that is passed as an argument (it could be SmallFileFilter, or LargeFileFilter) with an argument named item.
I guess, the benefit of programming with delegates this way is pretty clear. I have the flexibility of defining as many methods as I want, but my PrintAllFiles does not change. I could write another filter tomorrow, as long as it returns a bool and accepts an FileInfo object, I would be able to pass it to my PrintAllFiles method.
Now, we created a delegate, we wrote methods with names SmallFileFilter and LargeFileFilter, and then we invoked it. Couple of options here:
condition(item) would Invoke the method passed as an argument
condition.Invoke(item) would Invoke the method passed as an argument, just as the previous one did
condition.BeginInvoke(item) would Invoke the method passed as an argument in an asynchronous manner.
The essence here is the PrintAllFiles method that accepts a FileFilterDelegate. We could call it like below, by passing it the methods that match the FileFilterDelegate definition.
Using Anonymous Delegates
We created methods named SmallFileFilter and LargeFileFilter, for a reason being that’s how we were accustomed to write a method. Think of some cool names and name the method that way, so I could use that name and call it over and over, or pass it as a delegate argument over and over.
But instead, it I wanted a filter for one-off usage, I really don’t want to create a method and give it a name. I could simply write a method on the fly without a name. how’d I do that? Well, we are talking about Anonymous delegates already.
See the code below, it is just a method right there, without a name. All that is missing there is private static bool SmallFileFilter, private static bool LargeFileFilter; that are essentially replaced by the keyword delegate.
Now I don’t really need a method with a name. I could just write a method without a name on the fly and that would be considered an anonymous delegate if we prefixed it with the delegate keyword. Point to understand is we didn’t really eliminate the need to write methods, we just eliminated the need to name them.
Lets do some lambdas
We know how to write a method without a name, a method that was supposed to be passed as an argument. We did that by using the delegate keyword. Now as they wanted to make things simple and simple everyday, they made us put a lambda ( => ) instead of the delegate keyword.
That’s it! We saw how to create a delegate, how to write a method matching the delegate, how to pass it as an argument, how to invoke it.
..and there was this need to not name a method.. we preferred Anonymous Delegates
….then saw how to oust anonymous delegate with a lambda expression.
I guess I have stayed and not swayed from the title of the post. Although, these are not the only uses of lambda, this is one way, you can get a grip on if your lambda highway is slippery yet. Other great articles about lambda expressions, and it’s uses are below. If they are in too detail, a glance would do, that’s what I did.
Complete source code to test the samples and play with it.
Tags: understanding lambda, lambda expressions, lambda as anonymous delegates, lambda as function pointers in c#, anonymous delegations and lambda expressions