This small post is a follow-up of my previous post in which I discussed some common scenarios and how we can handle them in our LINQ queries. This time, we will see how to write queries that have not-so-simple conditions as join predicates. Note that LINQ directly supports only equi-joins, that is, joins based on equal conditions. Hence, for simple primary / foreign key fields, we can simply use the syntax:
from c in Customers join o in Orders on c.CustomerID equals o.CustomerID
For composite primary / foreign keys, we need to create an anonymous type with same data type and member names in the join predicate:
from c in Customers
join o in Orders on new {c.CompanyID, c.CustomerID} equals {o.CompanyID, o.CustomerID}
However, sometimes, we have join predicates that do not check equality, e.g. our join condition is based on a between check as in the following T-SQL query.
Select .. from Order o join AccountingPeriod ap on o.OrderDate between ap.PeriodStart and ap.PeriodEnd
Such situation can be handled in LINQ by using an always true join condition and transferring the join predicate to the where part. Here’s the LINQ translation for the above SQL query:
from o in dc.Orders join ap in dc.AccountingPeriods on true equals true where o.OrderDate >= ap.PeriodStart && o.OrderDate <= ap.PeriodEnd select …
Ane even better version as pointed by zn00p in the comments section is:
from o in dc.Orders from ap in dc.AccountingPeriods where o.OrderDate >= ap.PeriodStart && o.OrderDate <= ap.PeriodEnd select …
Notice that this concept is valid for inner joins only. Since for inner joins, the join predicate can be moved to the where part of the TSQL query. The above trick is valid for both LINQ to SQL and LINQ to Entities (Entity Framework).
April 13, 2010 at 11:12 PM
LINQ: How to write queries with complex join conditions « Mehroz’s Experiments…
Thank you for submitting this cool story – Trackback from DotNetShoutout…
April 14, 2010 at 5:57 PM
I don’t understand why you will need this:
from c in Customers
join o in Orders on c.CustomerID equals o.CustomerID
in a well desgined model you will need something more like:
from c in Customers from o in c.Orders;
April 14, 2010 at 6:28 PM
why not just use another from instead of this allways true condition …
from o in dc.Orders
from ap in dc.AccountingPeriods
where o.OrderDate >= ap.PeriodStart && o.OrderDate <= ap.PeriodEnd
select …
April 14, 2010 at 8:47 PM
@ivowiblo
Agreed. If the database has relationships defined then the implicit version you posted is more preferable.
@zn00p
That’s even better! I will update the post with this approach. Thanks for sharing.
September 18, 2010 at 10:26 PM
from o in dc.Orders
join ap in dc.AccountingPeriods on true equals true
where o.OrderDate >= ap.PeriodStart && o.OrderDate <= ap.PeriodEnd
select …
and how could i write this query in vb.net? i tried but the compiler says that i cannot put TRUE because i need one field from first table before EQUALS, and one field from the second one after EQUALS
July 8, 2011 at 11:24 AM
wahhh..
July 8, 2011 at 11:25 AM
dhiraj khobragade
October 27, 2011 at 2:04 AM
How do you perform multiple select returns…. returning certain fields from the domainservice???