The last two foundations of LINQ shed light on its flexibility and power. If you understand these two features and how to use them, you will be able to tap into some very powerful technology. Of course, this chapter only introduces these features; they are discussed in more detail in the rest of the book.
LINQ queries are composable: You can combine them in multiple ways, and one query can be used as the building block for yet another query. To see how this works, let’s look at a simple query:
var query = from customer in db.Customers where customer.City == "Paris" select customer;
The variable that is returned from the query is sometimes called a computation. If you write a foreach loop and display the address field from the customers returned by this computation, you see the following output:
265, boulevard Charonne 25, rue Lauriston
You can now write a second query against the results of this query:
query2 = from customer in query where customer.Address.StartsWith("25") select customer;
Notice that the last word in the first line of this query is the computation returned from the previous query. This second query produces the following output:
25, rue Lauriston
LINQ to Objects queries are composable because they operate on and usually return variables of type IEnumerable<T>. In other words, LINQ queries typically follow this pattern:
IEnumerable<T> query = from x in IEnumerable<T> select x;
This is a simple mechanism to understand, but it yields powerful results. It allows you to take complex problems, break them into manageable pieces, and solve them with code that is easy to understand and easy to maintain. You will hear much more about IEnumerable<T> in the next chapter.
The next chapter also details a feature called deferred execution. Although it can be confusing to newcomers, one of the benefits of deferred execution is that it allows you to compose multiple queries and string them together without necessarily needing to have each query entail an expensive hit against the server. Instead, three or four queries can “execute” without ever sending a query across the wire to your database. Then, when you need to access the result from your query, a SQL statement is written that combines the results of all your queries and sends it across the wire only once. Deferred execution is a powerful feature, but you need to wait until the next chapter for a full explanation of how and why it works. The key point to grasp now is that it enables you to compose multiple queries as shown here, without having to take an expensive hit each time one “executes.”