Search code examples
c#linqjoinsql-to-linq-conversion

SQL to LINQ - Left Join Before Inner Join


So I have a SQL query that I would like to convert to LINQ.

Here is said query:

SELECT *
FROM DatabaseA.SchemaA.TableA ta
    LEFT OUTER JOIN DatabaseA.SchemaA.TableB tb
    ON tb.ShipId = ta.ShipId
    INNER JOIN DatabaseA.SchemaA.TableC tc
    ON tc.PostageId= tb.PostageId
WHERE tc.PostageCode = 'Package'
      AND ta.MailId = 'Specification'

The problem I am struggling with is I cannot seem to figure out how to do a left join in LINQ before an inner join, since doing a left join in LINQ is not as clear to me at least.

I have found numerous examples of a LINQ inner join and then a left join, but not left join and then inner join.

If it helps, here is the LINQ query I have been playing around with:

var query = from m in tableA
join s in tableB on m.ShipId equals s.ShipId into queryDetails
from qd in queryDetails.DefaultIfEmpty()
join p in tableC on qd.PostageId equals p.PostageId
where m.MailId == "Specification" && p.PostageCode == "Package"
select m.MailId;

I have tried this a few different ways but I keep getting an "Object reference not set to an instance of an object" error on qd.PostageId.

LINQ is very new to me and I love learning it, so any help on this would be much appreciated. Thanks!


Solution

  • Use:

    var query = from m in tableA
    join s in tableB on m.ShipId equals s.ShipId
    join p in tableC on s.PostageId equals p.PostageId
    where m.MailId == "Specification" && p.PostageCode == "Package"
    select m.MailId;
    

    Your query uses a LEFT OUTER JOIN but it doesn't need it.

    It will, in practice, function as an INNER JOIN due to your tc.PostageCode = 'Package' clause. If you compare to a column value in a table in a WHERE clause (and there are no OR clauses and you aren't comparing to NULL) then effectively all joins to get to that table will be treated as INNER).

    That clause will never be true if TableB is null (which is why you use LEFT OUTER JOIN vs INNER JOIN) - so you should just use an INNER JOIN to make the problem simpler.