Usuário com melhor resposta
Entity Framework, Consulta com 2 ou mais joins usando expressão Lambda

Pergunta
-
Pessoal como que se faz pra realizar uma consulta no banco de dados usando expressões Lambda e dois ou mais Joins?
Eu consigo fazer usando o Linq dessa maneira:
var relatorio = (from c in Cnoperacao.tb_operacao_calltype
join r1 in Cnoperacao.tb_operacao_calltype_reason1 on c.id_reason1 equals r1.cod_reason into c_r1
join r2 in Cnoperacao.tb_operacao_calltype_reason2 on c.id_reason2 equals r2.cod_reason into c_r2
where c.data >= datainicial && c.data <= datafinal
from r1 in c_r1.DefaultIfEmpty()
from r2 in c_r2.DefaultIfEmpty()
select new {
Data = c.data,
Reason1 = r1.nm_reason== null ? "-" : r1.nm_reason,
Reason2 = r2.nm_reason== null ? "-" : r2.nm_reason}).ToList();Eu queria aprender como fazer essa consulta usando expressões Lambda, com um join eu até consegui, confesso que não entendi muito bem, mas com dois ou mais joins não achei nada que explicasse.
Alguém poderia me ajudar?
Respostas
-
GroupJoin
var groupJoin = db.Produto .GroupJoin(db.Categoria, pr => pr.CategoriaId, ca => ca.Id, (pr, ca) => new { pr, ca }) .GroupJoin(db.Tipo, pr => pr.pr.TipoId, ti => ti.Id, (pr, ti) => new { pr, ti }) .SelectMany(temp => temp.ti.DefaultIfEmpty(), (pr, ca) => new { pr, ca }) .SelectMany(temp => temp.pr.pr.ca.DefaultIfEmpty(), (a, b) => new { CatId = a.pr.pr.pr.CategoriaId, CatNome = a.pr.pr.pr.Categoria.Nome, TipId = a.pr.pr.pr.TipoId, TipNome = a.pr.pr.pr.Tipo.TipoDescricao, ProId = a.pr.pr.pr.Id, ProNome = a.pr.pr.pr.Descricao }).AsQueryable();
é bem parecido mas, utilize o GroupJoin com SelectMany para fazer esse tipo de agregação!
Só dará certo o LetJoin (porque o framework analisa se realmente tem as condições para realizar tal SQL)
é a mesma coisa mas, vai ter que mudar na parte do SelectMany !!!
Exemplo simples no meu Blog:
- Editado Fulvio Cezar Canducci Dias quarta-feira, 26 de fevereiro de 2014 14:33
- Sugerido como Resposta Fulvio Cezar Canducci Dias quarta-feira, 26 de fevereiro de 2014 14:33
- Marcado como Resposta Diego R Sousa - ds2web quarta-feira, 26 de fevereiro de 2014 14:56
Todas as Respostas
-
Realmente !!! é bem dificil de encontrar !!!
Vamos lá!
Nesse modelo acima perceba que a Tabela Produtos tem 2 Relacionamentos de Tipo e Categoria, para que eu pegue a descrição dessas tabelas precisamos de Joins !!!
Em Lambda seria:
using (AppDbEntities db = new AppDbEntities()) { var Joins = db.Produto .Join(db.Tipo, pr => pr.TipoId, ti => ti.Id, (pr, ti) => new { pr, ti }) .Join(db.Categoria, pr1 => pr1.pr.CategoriaId, ca => ca.Id, (pr1, ca) => new { pr1, ca }) .Select(x => new { CategoriaId = x.ca.Id, CategoriaNome = x.ca.Nome, TipoId = x.pr1.ti.Id, TipoNome = x.pr1.ti.TipoDescricao, ProdutoId = x.pr1.pr.Id, ProdutoDescricao = x.pr1.pr.Descricao }).AsQueryable(); var Results = Joins.ToArray(); }
Perceba que quanto mais Joins mais complicado fica mas, é assim que funciona ...
SQL Gerada! (Importante)
SELECT [Extent1].[Id] AS [Id], [Extent3].[Id] AS [Id1], [Extent3].[Nome] AS [Nome], [Extent2].[Id] AS [Id2], [Extent2].[TipoDescricao] AS [TipoDescricao], [Extent1].[Descricao] AS [Descricao] FROM [dbo].[Produto] AS [Extent1] INNER JOIN [dbo].[Tipo] AS [Extent2] ON [Extent1].[TipoId] = [Extent2].[Id] INNER JOIN [dbo].[Categoria] AS [Extent3] ON [Extent1].[CategoriaId] = [Extent3].[Id]
Perceba que tem alguns comando do proprio Framework ORM, mas, ele faz o Joins corretamente !!!
- Sugerido como Resposta Fulvio Cezar Canducci Dias terça-feira, 25 de fevereiro de 2014 22:16
-
Obrigado Fúlvio foi de grane ajuda, pois acho que entendi como funciona a lógica porém eu tenho o seguinte cenáiro:
var relatorio = Cnoperacao.tb_operacao_calltype .Join(Cnoperacao.tb_operacao_calltype_reason1, c => c.id_reason1, r1 => r1.cod_reason, (c, r1) => new { c, r1 }) .Join(Cnoperacao.tb_operacao_calltype_reason2, c1 => c1.c.id_reason2, r2 => r2.cod_reason, (c1, r2) => new { c1, r2 }) .Join(Cnoperacao.tb_operacao_calltype_reason3, c2 => c2.c1.c.id_reason3, r3 => r3.cod_reason, (c2, r3) => new { c2, r3 }) .Join(Cnoperacao.tb_operacao_familia, c3 => c3.c2.c1.c.id_familia, f => f.cod_familia, (c3, f) => new { c3, f }) .Join(Cnoperacao.tb_operacao_produto, c4 => c4.c3.c2.c1.c.id_produto, p => p.cod_produto, (c4, p) => new { c4, p }) .Join(Cnoperacao.tb_operacao_calltype_setor, c5=>c5.c4.c3.c2.c1.c.id_setor,s=>s.cod_setor,(c5,s)=>new{c5,s}) .Where(x => x.c5.c4.c3.c2.c1.c.data >= datainicial && x.c5.c4.c3.c2.c1.c.data<=datafinal) .Select(x => new{ ID = x.c5.c4.c3.c2.c1.c.cod_call_type, Data = x.c5.c4.c3.c2.c1.c.data, NR_Chamado = x.c5.c4.c3.c2.c1.c.nr_chamado, Reason1 = x.c5.c4.c3.c2.c1.r1.nm_reason, Reason2 = x.c5.c4.c3.c2.r2.nm_reason, Reason3 = x.c5.c4.c3.r3.nm_reason, Familia = x.c5.c4.f.nm_familia, Produto = x.c5.p.nm_produto, Primeiro_Contato = x.c5.c4.c3.c2.c1.c.ds_primeiroContato, Setor = x.s.nm_setor}).ToList();
Tenho 6 tabelas de relacionamento para este sistema, consegui fazer da maneira acima, porém acontece que em alguns casos o campo Reason3 e Setor serão nulos, e fazendo desta forma o inner join não traz a linha que tenha algum campo nulo.
Como se faz um Left Join pra poder retornar todas as linhas com campos nulos ou não?
-
GroupJoin
var groupJoin = db.Produto .GroupJoin(db.Categoria, pr => pr.CategoriaId, ca => ca.Id, (pr, ca) => new { pr, ca }) .GroupJoin(db.Tipo, pr => pr.pr.TipoId, ti => ti.Id, (pr, ti) => new { pr, ti }) .SelectMany(temp => temp.ti.DefaultIfEmpty(), (pr, ca) => new { pr, ca }) .SelectMany(temp => temp.pr.pr.ca.DefaultIfEmpty(), (a, b) => new { CatId = a.pr.pr.pr.CategoriaId, CatNome = a.pr.pr.pr.Categoria.Nome, TipId = a.pr.pr.pr.TipoId, TipNome = a.pr.pr.pr.Tipo.TipoDescricao, ProId = a.pr.pr.pr.Id, ProNome = a.pr.pr.pr.Descricao }).AsQueryable();
é bem parecido mas, utilize o GroupJoin com SelectMany para fazer esse tipo de agregação!
Só dará certo o LetJoin (porque o framework analisa se realmente tem as condições para realizar tal SQL)
é a mesma coisa mas, vai ter que mudar na parte do SelectMany !!!
Exemplo simples no meu Blog:
- Editado Fulvio Cezar Canducci Dias quarta-feira, 26 de fevereiro de 2014 14:33
- Sugerido como Resposta Fulvio Cezar Canducci Dias quarta-feira, 26 de fevereiro de 2014 14:33
- Marcado como Resposta Diego R Sousa - ds2web quarta-feira, 26 de fevereiro de 2014 14:56
-