Проблемът е, че проверявате годината, града и QsNo на OutPut
променлива след присъединяването... но ако OutPut е null (което би се случило, ако няма редове в AllCosts), тогава тези проверки винаги ще бъдат неверни, така че двойката (код, OutPut) ще бъде филтрирана от клаузата where. EF открива този факт и генерира заявка, която е по-ефективна само чрез използване на вътрешно свързване.
Това, което наистина искате да направите, е да филтрирате кандидат редове от Разходи, вместо да филтрирате по двойки (код, цена). За да направите това, можете да преместите филтъра си нагоре, така че да се прилага директно към таблицата с разходи:
var Result = from code in ent.ProductCodes
join cost
in ent.Costs.Where(c => c.Year == Year && c.City == City && c.QsNo == Qsno)
on new { code.Year, code.Code } equals new { cost.Year, cost.Code }
into AllCosts
from OutPut in AllCosts.DefaultIfEmpty()
where code.PageNo == PageNo
select new
{
ProductCode = code.Code
Col6 = OutPut.Price
};