views:

46

answers:

2

I have read plenty of blog posts and have yet to find a clear and simple example of how to perform a LEFT OUTER JOIN between two tables. The Wikipedia article on joins Join (SQL) provides this simple model:

CREATE TABLE `employee` (
`LastName` varchar(25),
`DepartmentID` int(4),
UNIQUE KEY `LastName` (`LastName`)
);

CREATE TABLE `department` (
`DepartmentID` int(4),
`DepartmentName` varchar(25),
UNIQUE KEY `DepartmentID` (`DepartmentID`)
);

Assume we had a EmployeeSet as an employee container ObjectSet<Employee> EmployeeSet and a DepartmentSet ObjectSet<Department> DepartmentSet. How would you perform the following query using Linq?

SELECT LastName, DepartmentName
FROM employee e 
  LEFT JOIN department d 
    ON e.DepartmentID = d.DepartmentID
A: 

You need to use the DefaultIfEmpty method :

var query =
    from e in db.EmployeeSet
    join d in db.DepartmentSet on e.DepartmentID equals d.DepartmentID into temp
    from d in temp.DefaultIfEmpty()
    select new { Employee = e, Department = d };
Thomas Levesque
I wanted to give you both +1 for useful answers but didn't realize that I was limited in voting. This answer is more generic and allows for a right outer join which was something I also needed to do in my application code. Could you explain what is happening on the line 'from d in temp.DefaultIfEmpty()'?
dcompiled
`DefaultIfEmpty` returns a sequence containing a single element with the default value (null in that case) if the input sequence is empty. So, if there is no Department that matches the DepartmentID of the employee, `temp.DefaultIfEmpty()` only contains null. The second `from` clause associates each element of `db.EmployeeSet` with each element of `temp.DefaultIfEmpty()`
Thomas Levesque
+1  A: 

I would write this, which is far simpler than join and does exactly the same thing:

var q = from e in db.EmployeeSet
        select new 
        {
            LastName = e.LastName,
            DepartmentName = e.Department.DepartmentName
        };
Craig Stuntz
This answer is 'cleaner' but requires a relationship between employee and department.
dcompiled
You don't have a foreign key?!?
Craig Stuntz
@Craig, what you're doing is not an outer join... According to the original SQL query, `e.Department` could be null, so your code could cause a `NullReferenceException`
Thomas Levesque
@Thomas, that is completely wrong. LINQ to Entities coalesces nulls, unlike to LINQ to objects. Try it yourself. L2E and L2O have different rules. You will *never* see a `NullReferenceException` in a purely L2E query.
Craig Stuntz
@Craig, good to know... I didn't know that. Now that I think of it, it makes sense, since the projection is also done in SQL
Thomas Levesque