Databases Reference
In-Depth Information
To eliminate ambiguity, here the static
Join
method of the
Queryable
class is called explic-
itly, not as an extension method. This is the lowest-level code you can write in C# to
create a LINQ query, but it still hides a lot of complexity. As you can see from its declara-
tion shown next, the
Join
method is
generic
:
public static IQueryable<TResult> Join<TOuter, TInner, TKey, TResult>(
this IQueryable<TOuter> outer,
IEnumerable<TInner> inner,
Expression<Func<TOuter, TKey>> outerKeySelector,
Expression<Func<TInner, TKey>> innerKeySelector,
Expression<Func<TOuter, TInner, TResult>> resultSelector
)
It is a bit overwhelming trying to understand something so abstract. You might find it
helpful to look at the
Join
method with specific parameters, which you can do by writing
a sample query in Visual Studio and pointing the mouse cursor at the method name to see
the tooltip while stepping over it in debugger. Here is what the debugger displays for this
sample query:
IQueryable<Product> Queryable.Join<Product, Supplier, int?, Product> (
IQueryable<Product> outer,
IEnumerable<Supplier> inner,
Expression<Func<Product, int?>> outerKeySelector,
Expression<Func<Supplier, int?>> innerKeySelector,
Expression<Func<Product, Supplier, Product>> resultSelector)
To break it down into smaller pieces, the
outer
parameter is the query that returns child
entities, and the
inner
parameter is the query that returns parent entities—in this example,
products and suppliers, respectively. When no additional filter criteria is applied to either
query, these parameters could be simply
context.Products
and
context.Suppliers
,
respectively, resulting in a join performed between the two entire tables. From the stand-
point of the Parent filter template, you do not need to worry about constructing these
parameters with LINQ expression objects. The
GetQueryable
method receives the first
query as its argument, and the nested filter template builds the second query.
The
outerKeySelector
parameter is a lambda expression that takes a Product entity as a
parameter and returns value of its SupplierID property. In the original query, this looks
simply like
p => p.SupplierID
; however, with LINQ expression objects, building the key
selector is a little more involved. Here is how you could do it:
ParameterExpression parameter = Expression.Parameter(typeof(Product));
MemberExpression property = Expression.Property(parameter, “SupplierID”);
LambdaExpression
productKeySelector
= Expression.Lambda(
property, parameter);
The
innerKeySelector
parameter is very similar, only it takes a Supplier entity as a para-
meter and returns value of its
SupplierID
property. In the original query, it looked like
this:
s => s.SupplierID
. What you don't see, however, is that the compiler automatically