Compiling lambdas expressions to code
delegates works great when we want to evaluate them against in-memory data like
with our List collection above. But consider cases where you want to
query data from a database (the code below was written using the built-in LINQ
to SQL object relational mapper in "Orcas"):
Listing 7

Here I am retrieving a sequence of strongly
typed "Product" objects from a database, and I am expressing a filter
to use via a Lambda expression to a Where() extension method.
What I absolutely do not want to have
happen is to retrieve all of the product rows from the database, surface them
as objects within a local collection, and then run the same in-memory Where()
extension method above to perform the filter. This would be hugely
inefficient and not scale to large databases. Instead, I'd like the LINQ
to SQL ORM to translate my Lambda filter above into a SQL expression, and perform
the filter query in the remote SQL database. That way I'd only
return those rows that match the query (and have a very efficient database
lookup).
Framework developers can achieve this by
declaring their Lambda expression arguments to be of type Expression<T>
instead of Func<T>. This will cause a Lambda expression argument to
be compiled as an expression tree that we can then piece apart and analyze at
runtime:
Listing 8

Note above how I took the same
p=>p.LastName == "Guthrie" Lambda expression that we used earlier,
but this time assigned it to an Expression<Func<Person, bool>>
variable instead of a Func<Person,bool> datatype. Rather then
generate IL, the compiler will instead assign an expression tree object that I
can then use as a framework developer to analyze the Lambda expression and
evaluate it however I want (for example, I could pick out the types,
names and values declared in the expression).
In the case of LINQ to SQL, it can take
this Lambda filter statement and translate it into standard relational SQL
to execute against a database (logically a "SELECT * from Products where
UnitPrice < 55").
<span lang=EN>IQueryable<T> Interface</span>
To help framework developers build
query-enabled data providers, LINQ ships with the IQueryable<T>
interface. This implements the standard LINQ extension method query
operators, and provides a more convenient way to implement the processing of a
complex tree of expressions (for example: something like the below scenario
where I'm using three different extension methods and two lambdas to retrieve
10 products from a database):
Listing 9

For some great blog post series that cover how to build
custom LINQ enabled data providers using IQueryable<T>, please check out
these great blog posts from others below:
LINQ to Amazon: Part 1, Part 2, Part 3
LINQ to NHibernate: Part 1, Part 2, Part 3
LINQ to LDAP: Part 0, Part 1, Part 2, Part 3, Part 4, Part 5