To generate this type of SQL you must use the methods Groupjoin with Selectmany to have the same effect as the SQL requested. The examples below prove the generation of the same SQL, note:
Linq
using (ObjEntities cx = new ObjEntities())
{
var resultLinq = (from pessoa in cx.Pessoa
join pessoapai in cx.Pessoa on pessoa.PessoaPaiId equals pessoapai.PessoaId into Pai
from P in Pai.DefaultIfEmpty()
join pessoamae in cx.Pessoa on pessoa.PessoaMaeId equals pessoamae.PessoaId into Mae
from M in Mae.DefaultIfEmpty()
select new
{
pessoa.PessoaId,
pessoa.Nome,
pessoa.PessoaPaiId,
NomePai = P.Nome,
pessoa.PessoaMaeId,
NomeMae = M.Nome
})
.ToList();
}
Lambda:
using (ObjEntities cx = new ObjEntities())
{
var resultLambda = cx.Pessoa
.GroupJoin(cx.Pessoa, pessoa => pessoa.PessoaPaiId, pessoapai => pessoapai.PessoaId, (pessoa, pessoapai) => new { pessoa, pessoapai })
.SelectMany(a => a.pessoapai.DefaultIfEmpty(), (c, d) => new
{
c.pessoa.PessoaId,
c.pessoa.Nome,
NomePai = d.Nome,
c.pessoa.PessoaPaiId,
c.pessoa.PessoaMaeId
})
.GroupJoin(cx.Pessoa, pessoa => pessoa.PessoaMaeId, pessoamae => pessoamae.PessoaId, (pessoa, pessoamae) => new { pessoa, pessoamae })
.SelectMany(b => b.pessoamae.DefaultIfEmpty(), (e, f) => new {
e.pessoa.PessoaId,
e.pessoa.Nome,
e.pessoa.PessoaPaiId,
NomePai = e.pessoa.NomePai,
e.pessoa.PessoaMaeId,
NomeMae = f.Nome
})
.ToList();
}
The SQL generation of the two encoding style types is equal to the question:
SELECT
[Extent1].[PessoaId] AS [PessoaId],
[Extent1].[Nome] AS [Nome],
[Extent1].[PessoaPaiId] AS [PessoaPaiId],
[Extent2].[Nome] AS [Nome1],
[Extent1].[PessoaMaeId] AS [PessoaMaeId],
[Extent3].[Nome] AS [Nome2]
FROM [dbo].[Pessoa] AS [Extent1]
LEFT OUTER JOIN [dbo].[Pessoa] AS [Extent2] ON [Extent1].[PessoaPaiId] = [Extent2].[PessoaId]
LEFT OUTER JOIN [dbo].[Pessoa] AS [Extent3] ON [Extent1].[PessoaMaeId] = [Extent3].[PessoaId]
Debug
References: