Supondo que eu tenho uma junção externa esquerda como tal:
from f in Foo
join b in Bar on f.Foo_Id equals b.Foo_Id into g
from result in g.DefaultIfEmpty()
select new { Foo = f, Bar = result }
Como eu expressaria a mesma tarefa usando métodos de extensão? Por exemplo
Foo.GroupJoin(Bar, f => f.Foo_Id, b => b.Foo_Id, (f,b) => ???)
.Select(???)
c#
linq-to-sql
lambda
LaserJesus
fonte
fonte
GroupJoin
, a junção externa esquerda, aSelectMany
peça é necessária apenas dependendo do que você deseja selecionar.Como essa parece ser a questão SO de fato para junções externas esquerdas usando a sintaxe do método (extensão), pensei em adicionar uma alternativa à resposta atualmente selecionada que (pelo menos em minha experiência) tem sido mais comumente o que eu sou depois de
Para exibir a diferença usando um conjunto de dados simples (supondo que estamos juntando os próprios valores):
A opção 2 é verdadeira para a definição de junção externa esquerda típica, mas como mencionei anteriormente, muitas vezes é desnecessariamente complexo, dependendo do conjunto de dados.
fonte
Single
verificação facilmente em meio a uma junção.SingleOrDefault
no entanto, é uma maneira mais "correta" de demonstrar essa IMO.O método Group Join é desnecessário para obter a junção de dois conjuntos de dados.
Junção interna:
Para a associação à esquerda, basta adicionar DefaultIfEmpty ()
EF e LINQ to SQL transformam corretamente em SQL. Para o LINQ to Objects, é melhor participar usando o GroupJoin, pois ele usa a Pesquisa internamente . Mas se você estiver consultando o banco de dados, ignorar o GroupJoin é o AFAIK como performant.
O Personlay para mim dessa maneira é mais legível em comparação com GroupJoin (). SelectMany ()
fonte
Você pode criar um método de extensão como:
fonte
Aprimorando a resposta da Ocelot20, se você tiver uma tabela com a qual você se uniu, onde você deseja apenas 0 ou 1 linhas, mas pode ter várias, você precisa ordenar a sua tabela unida:
Caso contrário, qual linha você obterá na junção será aleatória (ou mais especificamente, o que o banco de dados encontrar primeiro).
fonte
Transformando a resposta de Marc Gravell em um método de extensão, fiz o seguinte.
fonte
Enquanto a resposta aceita funciona e é boa para o Linq to Objects, me incomodou que a consulta SQL não fosse apenas uma junção externa esquerda direta.
O código a seguir baseia-se no projeto LinkKit, que permite passar expressões e invocá-las para sua consulta.
Pode ser usado da seguinte maneira
fonte
Existe uma solução fácil para isso
Basta usar .HasValue no seu Select
Muito fácil, sem necessidade de participar de grupos ou qualquer outra coisa
fonte