Предложение "join" (а не "join ... into") в выражении запроса переводится в вызов Join. Сложный бит - прозрачные идентификаторы - из соединения выходит только одна последовательность, и в нем должны быть и t
, и l
(в вашем примере), так что компилятор совершает магию.
У меня не так много времени, чтобы вдаваться в детали, но, вероятно, лучше просто показать вам, как переводится выражение вашего запроса.
Это:
from t in Tasks
join l in Labels on t.TaskId equals l.SourceId
where l.Name == "accounting"
select t
Переводится на:
Tasks.Join(Labels, t => t.TaskId, l => l.SourceId, (t, l) => new { t, l })
.Where(z => z.l.Name == "accounting")
.Select(z => z.t)
Обратите внимание на введение "z" здесь - в основном, оно содержит и t, и l из исходного выражения.
РЕДАКТИРОВАТЬ: ответ Дэвида Мортона дает более эффективный способ сделать это. Его строка эквивалентна:
from t in Tasks
join l in (from x in Labels where x.Name == "accounting")
on t.TaskId equals l.SourceId
select t
Если у вас есть только предложение select после объединения, компилятор может пропустить прозрачный идентификатор и поместить проекцию непосредственно как последний параметр в вызове Join.