Вам следует избегать установки условий на переменные диапазона, поступающие с правой стороны от left outer join
, так как это эффективно превращает их в inner join
.
Вместо этого, вы должны либо применить правую сторону фильтрации перед тем объединения:
from a in TableA
where id = 1
join b in TableB.Where(x => a.Active)
on a.table2 equals b.id
into ab
from bdata in ab.DefaultIfEmpty()
join c in TableC.Where(x => x.Active)
on a.table3 equals c.id
into ac
from cdata in ac.DefaultIfEmpty()
...
или включить их в соединении (если это возможно):
from a in TableA
where id = 1
join b in TableB
on new { id = a.table2, Active = true } equals new { b.id, b.Active }
into ab
from bdata in ab.DefaultIfEmpty()
join c in TableC
on new { id = a.table3, Active = true } equals new { c.id, c.Active }
into ac
from cdata in ac.DefaultIfEmpty()
...
Для того, чтобы понять, почему это, попытайтесь оценить where bdata.Active == true
, когда bdata
- null
(т. е. нет соответствующей записи). На самом деле, если это LINQ to Objects, приведенные выше критерии будут генерировать NullReferenceException
. Но LINQ to Entities может обрабатывать эти исключения без учета, поскольку базы данных, естественно, поддерживают значения null
в запросах для столбцов, которые обычно не имеют значения NULL. Таким образом, приведенное выше значение оценивается как false
, следовательно, фильтрует результирующую запись и эффективно удаляет эффект left outer join
, который по определению должен возвращать левую запись независимо от того, существует ли соответствующая правая боковая запись.
Это означает, что на самом деле есть третий путь (Althought первые два варианта является более предпочтительным) - включает явный null
проверку:
from a in TableA
where id = 1
join b in TableB
on a.table2 equals b.id
into ab
from bdata in ab.DefaultIfEmpty()
where bdata == null || bdata.Active
join c in TableC
on a.table3 equals c.id
into ac
from cdata in ac.DefaultIfEmpty()
where cdata == null || cdata.Active
...
, которая не возвращает 'null' но пустая коллекции. Запросы Linq не возвращают 'null' (если вы не извлекли из него определенную запись, которая может быть нулевой) –