Learning LINQ Part-1
Introduction
LINQ (Language Integrated Query) is a programming model that introduces queries as a regular programming concept into .NET Languages. LINQ syntax is more semantic and self explanatory. It provides a simple but most powerful environment to the developer by reducing code size.
LINQ can access data from several data sources like Plain .NET Objects like collections, LINQ to ADO.NET (using SQL, Datasets, and Entities) and the de-facto data representation standard XML.
The Main Problem with Embedded SQL is impedance mismatch and is neatly handled by LINQ. LINQ offers a uniform way to access and manage data without forcing the adoption of “One Syntax Fits for All” methodology.
LINQ is far better than embedded SQL. Embedded SQL has several restrictions and we cannot write query in the programming language native code where as in LINQ we can write programming language native code.
How does LINQ Code Looks Like
The sample below queries a list of strings and returns all strings with a length of five.
using System;
using System.Query;
class Program
{
static void Main(string[] args)
{
string[] aBunchOfWords = {“One”,”Two”, “Hello”,
“World”, “Four”, “Five”};
var result =
from s in aBunchOfWords // query the string array
where s.Length == 5 // for all words with length = 5
select s; // and return the string
//PrintToConsole is an Extension method that prints the value
result.Print();
}
}
This application prints the following result
Hello
World
The Need for LINQ
LINQ does create a new way of looking at enumerations of data, and gives out-of-the-box functionality for them. I have used as well as some odd examples that you might not have thought about as being ‘queryable objects’.
Basic LINQ Queries
Let’s look at some very simple examples of LINQ so that we can have a basis to grow on. Let’s pretend that we have a user control that has a variable amount of TextBoxes added to it (based on some database query or whatever). Our user control might have other controls (Buttons, Literals and the like), and we want to disable all of the TextBoxes if the user doesn’t have security permissions to edit these controls. Please keep in mind that this is a hypothetical scenario at this point just so we can see some basic LINQ (in this case, LINQ to Objects).
Now, you can do this a few ways. Because the number of TextBoxes is dynamic we would possibly do something like this:
// Loop through all of the controls.
foreach (Control myChildControl in this.Controls)
{
// Make sure the control is a TextBox.
if (myChildControl is TextBox)
{
// Cast that “Control” object to a TextBox and disable it.
((myChildControl)myChildControl).Enabled = false;
}
}
The above code isn’t really that bad, but I for one don’t like that I have to loop through all of my controls, check the type, cast it to the type that I just checked for, and then set my property. So, let’s see how LINQ will not only “pretty up” my code, but will also make more sense to us programmers:
// Define a enumeration only containing child TextBoxes.
var myChildTextBoxes = from myChildControl in this.Controls
where myChildControl is TextBox
select myChildControl;
// Loop through my TextBoxes.
foreach (TextBox myChildTextBox in myChildTextBoxes)
{
// Disable the TextBox.
myChildTextBox.Enabled = false;
}
This LINQ approach is much cleaner. It’s clear from the start that you want to work with a list of TextBoxes only. Secondly, you aren’t type checking, then re-type casting. Now, you might argue that you could avoid the second type-cast by using an “as” keyword and checking for nulls, or you could say that you don’t like how many lines of code this takes. Those are some valid claims, but if you are thinking that, then apparently you have a short attention span (as I mentioned above that this is just to get you a little familiar with the language syntax).
Querying Unconventional Data Sources
Once you begin to use LINQ a bit more in your C# (or VB), you’ll begin to think of ‘data sources’ in a different way. For instance, you may see a directory (a folder on your computer) as a data source of files. You can even start to look at your list of running processes as a data source. Really, no enumeration is safe!
What if you were to make a web application that allowed you to upload and download files from your home machine? Let’s say you had a DropDownList that would show a list of the files in the specified directory, perhaps with a button that lets you download it. How would you go about populating that DropDownList with clean file names for the “Text” property and perhaps the path for the “Value” property? I’ll go a step further and say that this is what you’re DropDownList looks like in ASP.NET:
<asp:DropDownList runat=”server”
DataTextField=”FileName” DataValueField=”FullPath” />
Well, you could create your own custom class that has a FileName property and a FullPath property. Then you could make a generic list of that class, loop through the files in a Directory.GetFiles method, add an entry for each file, set the list as the DataSource of the DropDownList and data bind. That’s a whole lot of nasty that I’m not even going to show the code for (really, because I never want to write nasty code like that again). Here’s what I would do using LINQ:
// Set the DataSource of our DropDownList to an enumeration of a new
// “anonymous type” (meaning a class that is being built on the fly)
// that contains the file names and full paths in our directory.
this.MyFilesList.DataSource = from file in Directory.GetFiles(somePath)
select new
{
FileName = Path.GetFileName(file),
FullPath = file
};
// Call the “DataBind” method 😛
this.MyFilesList.DataBind();
All I can say after that is “Go LINQ GO!” and of course “case closed!”
Extension Methods and Lambda Expressions
One more part to LINQ is the heavy use of Extension Methods and Lambda expressions to accomplish this beautiful language enhancement. If you remember our original example of disabling the TextBoxes, then you’re going to love one of the 50 STANDARD OPERATORS that are brought to you just by including a reference to the System.Linq namespace! Check this out:
// Loop through my TextBoxes.
foreach (TextBox myChildTextBox in this.Controls.OfType<TextBox>())
{
// Disable the TextBox.
myChildTextBox.Enabled = false;
}
Don’t check you’re MSDN… there is no method called “OfType” on the ControlCollection class. But, because the ControlCollection class implements the IEnumerable interface, it automatically gets all of the extension methods that LINQ has kindly given to any enumeration (such as “OfType” which I am using above).
LINQ can be done one of two ways (or a combination of both): query expressions or method expressions. The difference between the two is only a syntax difference, as they ultimately compile into the same thing. Example:
// This line of code…
var textBoxes = from control in this.Controls
where control is TextBox select control;
// is the same thing as this.
var textBoxes = this.Controls.OfType<TextBox>();
Lambda expressions come into play when you want to perform another standard operation such as “SUM” or “MAX”. Here’s an example that I have used recently. I wanted to make a property that displayed the “TotalBill” of an object that had child “orders” in it. Here’s how lambda helped out:
public decimal TotalBill
{
get
{
// Keep in mind that “Orders” is just a list of
// ‘Order’ objects and has no special functionality.
return this.Orders.Sum(order => order.Price);
}
}