Usuário com melhor resposta
Dúvida quanto a objeto de retorno no entity framework

Pergunta
-
Pessoal, boa noite.
Estou com algumas dúvidas com Linq e Entity framework.
Gostaria de saber qual seria a melhor opção para usar como objeto de retorno para um caso como o do código abaixo. Este código não está rodando, acredito eu pq estou querendo devolver um objeto do tipo List<STATUS> quando na verdade, a query não tem só registros de Status, mas também de uma outra tabela (TIPO_STATUS).
Outra coisa que vi ao pesquisar no fórums foi que algumas pessoas dizem ser melhor não usar o "var". Qual seriam as opções além do uso do "var"?
protected List<STATUS> GetStatus()
{
meuDb entities = new meuDb();
var status = from s in entities.STATUS
join ts in entities.TIPO_STATUS
on s.TIPO_STATUS.tst_int_codigo equals ts.tst_int_codigo
select new { s.sta_int_codigo, s.sta_str_descricao, ts.tst_str_descricao };
return status;
}
Abraços a todos e agradeço desde já.- Editado Eduardo_CWB segunda-feira, 1 de fevereiro de 2010 20:08 source desconfigurado
Respostas
-
Eduardo, você pode retornar um IList ou um IQueryable
Henrique Tambalo- Marcado como Resposta Eduardo_CWB quinta-feira, 4 de fevereiro de 2010 12:22
-
Claro!
Exemplo: imagine que você no banco de dados você tem uma tabela de Pessoas e outra de Clientes. A tabela de Pessoas tem uma coluna Nome e, a tabela de clientes tem uma coluna Nome_Empresa. Um modelo parecido com o do Adventure Works (vc conhece?)
Imagine que você precisa ter uma tela em seu sistema para a consulta de Clientes. Mas para consultar clientes precisa fazer um join e juntar o Pessoa.Nome com o Clientes.Nome_Empresa, ok?
Com o EF, você cria uma Entidade Cliente que é a junção das duas tabelas, portanto possui duas propriedades: Nome e NomeEmpresa. Quando usar um LINQ to Entities irá fazer uma consulta que retorna um List<Cliente>. Sem ter a necessidade de selecionar as tabelas. Irá fazer a consulta em Clientes (Entidade de negócio) onde cada objeto possui ambas propriedades. Ou seja, o join fica por conta do EF.
Será que melhorei ou piorei?
[]'s
Jorge Rua http://jtressino.spaces.live.com http://twitter.com/jtressino- Sugerido como Resposta Jorge Rua quarta-feira, 3 de fevereiro de 2010 00:02
- Marcado como Resposta Eduardo_CWB quinta-feira, 4 de fevereiro de 2010 12:19
-
Não está dando certo porque o método retorna uma List e você está retornando um anonymous tipe.
Tente fazer de 2 maneiras, retornar um iqueryable ou uma lista mesmo, vou dar os 2 exemplos:
Retornando Iqueryable.
Note que eu não fiz join, usei as propriedades de navegação do próprio objeto
//Busca todos os Produtos
public static IQueryable GetAllProduto()
{
try
{
Entities db = new Entities();
var results = (from p in db.Produto
select new
{
codigo = p.codigo,
descricao = p.descricao,
descricaoReduzida = p.descricaoReduzida,
descricaoECF = p.descricaoECF,
unidadeMedida = p.UnidadeMedida.codigo,
codGrupo = p.GrupoSubFamilia.codigoGrupo,
codGrupoSub = p.GrupoSubFamilia.codigoGrupoSub,
codGrupoSubFamilia = p.GrupoSubFamilia.codigoGrupoSubFamilia,
tipo = p.tipo,
ativo = p.ativo
}).OrderByDescending(p => p.codigo);
return results;
}
catch (Exception ex)
{
MessageBox.Show(ClassMessages.ErrorSelect + ex.Message);
return null;
}
}
Retornando List:
Neste caso eu retorei uma list de uma classe, mas você pode retornar um list de entidade perfeitamente.
Espero ter explicado as suas dúvidas!
//Busca todos os Produtos
public static List<ClassProduto> InstanceAllProdutos()
{
try
{
Entities db = new Entities();
var results = (from p in db.Produto
select new
{
codigo = p.codigo,
descricao = p.descricao,
descricaoReduzida = p.descricaoReduzida,
descricaoECF = p.descricaoECF,
unidadeMedida = p.UnidadeMedida.codigo,
codGrupo = p.GrupoSubFamilia.codigoGrupo,
codGrupoSub = p.GrupoSubFamilia.codigoGrupoSub,
codGrupoSubFamilia = p.GrupoSubFamilia.codigoGrupoSubFamilia,
tipo = p.tipo,
ativo = p.ativo,
dataInclusao = p.dataInclusao,
dataUltimaAtualizacaoCadastral = p.dataUltimaAtualizacaoCadastral,
usuario = p.Usuario.codigo
}).OrderBy(p => p.codigo);
List<ClassProduto> listProduto = new List<ClassProduto>();
foreach (var regProd in results)
{
ClassProduto prod = new ClassProduto();
prod.CodigoProduto = regProd.codigo;
prod.DescricaoProduto = regProd.descricao;
prod.DescricaoReduzidaProduto = regProd.descricaoReduzida;
prod.DescricaoECFProduto = regProd.descricaoECF;
prod.UnidadeMedidaProduto = regProd.unidadeMedida;
prod.CodigoGrupo = regProd.codGrupo;
prod.CodigoGrupoSub = regProd.codGrupoSub;
prod.CodigoGrupoSubFamilia = regProd.codGrupoSubFamilia;
prod.TipoProduto = regProd.tipo;
prod.AtivoProduto = regProd.ativo;
prod.DataInclusaoProduto = regProd.dataInclusao;
prod.DataUltimaAtualizacaoCadastralProduto = regProd.dataUltimaAtualizacaoCadastral;
prod.CodigoUsuario = regProd.usuario;
listProduto.Add(prod);
}
return listProduto;
}
catch (Exception ex)
{
MessageBox.Show(ClassMessages.ErrorSelect + ex.Message);
return null;
}
}- Marcado como Resposta Eduardo_CWB quinta-feira, 4 de fevereiro de 2010 12:20
Todas as Respostas
-
Olá Eduardo,
Para dar suporte ao LINQ foi implementado ao framework os Tipos Anônimos (Anonymous Types). Eles podem ser declarados com o uso do "var".
O objetivo de utilizar os tipos anônimos, como o próprio nome diz, é ter a facilidade de criar um tipo (classe) sem precisar declará-la. E, uma vez que você não a declara, não tem referenciá-la pois não tem nome, certo?
Quando você realiza uma query com LINQ e na cláusula SELECT vc utiliza SELECT NEW. Você acaba de utilizar um tipo anônimo. E, portanto não consegue utilizá-lo como parâmetro de retorno, uma vez que não possui tipo.
No seu caso, está querendo retornar um List<STATUS> portanto o SELECT do LINQ deve popular objetos do tipo STATUS. Portanto pode fazer assim SELECT NEW STATUS { (Aqui vc popula todas as propriedades de um objeto STATUS) }...
Consegui te ajudar? Espero que sim...
[]'s
Jorge Rua http://jtressino.spaces.live.com http://twitter.com/jtressino- Sugerido como Resposta Jorge Rua segunda-feira, 1 de fevereiro de 2010 21:01
-
Bom dia Jorge.
Desde de já agradeço sua atenção amigo.
Então, eu entendi o que vc me propôs, mas, o que eu necessito realmente não é retornar um objeto somente do tipo List<STATUS>, veja na minha query que além de STATUS eu também tenho um join com a tabela TIPO_STATUS .
O que eu preciso saber é qual objeto eu uso para retornar os valores obtidos nesta query onde eu tenho além da tabela STATUS também a tabela TIPO_STATUS.
Em resumo é como retornar um objeto que tenha propriedades de mais de uma tabela.
Vlw pela ajuda até agora amigão.
Abraços. -
Eduardo, você pode retornar um IList ou um IQueryable
Henrique Tambalo- Marcado como Resposta Eduardo_CWB quinta-feira, 4 de fevereiro de 2010 12:22
-
-
Eduardo,
Eu vi que você tem dados de mais de uma tabela/objeto a ser retornado. Porém isso não deveria ser assim.
Como você está utilizando o Entity Framework, você deve criar Entidades (de negócio) que expressem algo significativo ao negócio. E não usá-las como entidades de banco de dados. Esse é a razão de existir do Entity Framework. Se não, passe a usar o LINQ to SQL.
Em seu exemplo, me parece que a entidade de negócio que representa o STATUS deveria ter propriedades oriundas das duas tabelas. Se fizer isso, não será necessário fazer o join pelo LINQ. O EF se encarregará de fazer o join no select.
Mesmo assim, se necessitar retornar uma combinação de ambas entidades você precisa criar uma classe com as propriedades de ambas tabelas e, usá-la no LINQ.
Ex:
public class classedemo
{
public string prop1 {get; set;}
public string prop2 {get; set;}
}
No LINQ faça:
FROM... JOIN... WHERE... SELECT NEW classedemo {prop1 = s.sta_int_codigo, prop2 = ts.tst_str_descricao};
[]'s
Jorge Rua http://jtressino.spaces.live.com http://twitter.com/jtressino- Sugerido como Resposta Jorge Rua terça-feira, 2 de fevereiro de 2010 16:14
-
Olá Jorge.
Abaixo está o relacionamento entre as duas tabelas que eu coloquei no primeiro código:
http://img709.imageshack.us/img709/5452/statusrelacionamento.jpg //me desculpe, mas não consegui colocar a imagem direto.
Ainda estou começando em Entity Framework, então algumas coisas eu fiquei confuso com o que você falou, ex:
--"você deve criar Entidades (de negócio) que expressem algo significativo ao negócio"
mas não é o proprio frame que cria essas classes quando vc relaciona quais tabelas do banco vc quer?
Eu entendi vc dizer também que ao seu ver -- "a entidade de negócio que representa o STATUS deveria ter propriedades oriundas das duas tabelas". Mas isso não quer dizer que minha tabela STATUS no banco deve ter os campos da tabela TIPO_STATUS, e esta ultima desaparecer, correto? Como eu deveria criar essas entidades de negócios com ambas as propriedades?
Agradeço desde já pela atenção e paciência Jorge.
Abraços.- Editado Eduardo_CWB terça-feira, 2 de fevereiro de 2010 16:43
-
Imagina Eduardo,
Estamos aqui para ajudar!!!
Dá uma olhada nesse artigo, veja o que ele faz com a Entidade SalesOrders. É a junção das tabelas SalesOrder e StoreSalesOrder. Pq faz isso? Porque na visão de negócios não tem sentido exitir duas entidades em separado. Isso que eu quis dizer com "expressem algo significativo ao negócio".
http://msdn.microsoft.com/en-us/library/aa697427(VS.80).aspx
[]'s
Jorge Rua http://jtressino.spaces.live.com http://twitter.com/jtressino- Sugerido como Resposta Jorge Rua quarta-feira, 3 de fevereiro de 2010 00:02
-
-
Claro!
Exemplo: imagine que você no banco de dados você tem uma tabela de Pessoas e outra de Clientes. A tabela de Pessoas tem uma coluna Nome e, a tabela de clientes tem uma coluna Nome_Empresa. Um modelo parecido com o do Adventure Works (vc conhece?)
Imagine que você precisa ter uma tela em seu sistema para a consulta de Clientes. Mas para consultar clientes precisa fazer um join e juntar o Pessoa.Nome com o Clientes.Nome_Empresa, ok?
Com o EF, você cria uma Entidade Cliente que é a junção das duas tabelas, portanto possui duas propriedades: Nome e NomeEmpresa. Quando usar um LINQ to Entities irá fazer uma consulta que retorna um List<Cliente>. Sem ter a necessidade de selecionar as tabelas. Irá fazer a consulta em Clientes (Entidade de negócio) onde cada objeto possui ambas propriedades. Ou seja, o join fica por conta do EF.
Será que melhorei ou piorei?
[]'s
Jorge Rua http://jtressino.spaces.live.com http://twitter.com/jtressino- Sugerido como Resposta Jorge Rua quarta-feira, 3 de fevereiro de 2010 00:02
- Marcado como Resposta Eduardo_CWB quinta-feira, 4 de fevereiro de 2010 12:19
-
-
-
Não está dando certo porque o método retorna uma List e você está retornando um anonymous tipe.
Tente fazer de 2 maneiras, retornar um iqueryable ou uma lista mesmo, vou dar os 2 exemplos:
Retornando Iqueryable.
Note que eu não fiz join, usei as propriedades de navegação do próprio objeto
//Busca todos os Produtos
public static IQueryable GetAllProduto()
{
try
{
Entities db = new Entities();
var results = (from p in db.Produto
select new
{
codigo = p.codigo,
descricao = p.descricao,
descricaoReduzida = p.descricaoReduzida,
descricaoECF = p.descricaoECF,
unidadeMedida = p.UnidadeMedida.codigo,
codGrupo = p.GrupoSubFamilia.codigoGrupo,
codGrupoSub = p.GrupoSubFamilia.codigoGrupoSub,
codGrupoSubFamilia = p.GrupoSubFamilia.codigoGrupoSubFamilia,
tipo = p.tipo,
ativo = p.ativo
}).OrderByDescending(p => p.codigo);
return results;
}
catch (Exception ex)
{
MessageBox.Show(ClassMessages.ErrorSelect + ex.Message);
return null;
}
}
Retornando List:
Neste caso eu retorei uma list de uma classe, mas você pode retornar um list de entidade perfeitamente.
Espero ter explicado as suas dúvidas!
//Busca todos os Produtos
public static List<ClassProduto> InstanceAllProdutos()
{
try
{
Entities db = new Entities();
var results = (from p in db.Produto
select new
{
codigo = p.codigo,
descricao = p.descricao,
descricaoReduzida = p.descricaoReduzida,
descricaoECF = p.descricaoECF,
unidadeMedida = p.UnidadeMedida.codigo,
codGrupo = p.GrupoSubFamilia.codigoGrupo,
codGrupoSub = p.GrupoSubFamilia.codigoGrupoSub,
codGrupoSubFamilia = p.GrupoSubFamilia.codigoGrupoSubFamilia,
tipo = p.tipo,
ativo = p.ativo,
dataInclusao = p.dataInclusao,
dataUltimaAtualizacaoCadastral = p.dataUltimaAtualizacaoCadastral,
usuario = p.Usuario.codigo
}).OrderBy(p => p.codigo);
List<ClassProduto> listProduto = new List<ClassProduto>();
foreach (var regProd in results)
{
ClassProduto prod = new ClassProduto();
prod.CodigoProduto = regProd.codigo;
prod.DescricaoProduto = regProd.descricao;
prod.DescricaoReduzidaProduto = regProd.descricaoReduzida;
prod.DescricaoECFProduto = regProd.descricaoECF;
prod.UnidadeMedidaProduto = regProd.unidadeMedida;
prod.CodigoGrupo = regProd.codGrupo;
prod.CodigoGrupoSub = regProd.codGrupoSub;
prod.CodigoGrupoSubFamilia = regProd.codGrupoSubFamilia;
prod.TipoProduto = regProd.tipo;
prod.AtivoProduto = regProd.ativo;
prod.DataInclusaoProduto = regProd.dataInclusao;
prod.DataUltimaAtualizacaoCadastralProduto = regProd.dataUltimaAtualizacaoCadastral;
prod.CodigoUsuario = regProd.usuario;
listProduto.Add(prod);
}
return listProduto;
}
catch (Exception ex)
{
MessageBox.Show(ClassMessages.ErrorSelect + ex.Message);
return null;
}
}- Marcado como Resposta Eduardo_CWB quinta-feira, 4 de fevereiro de 2010 12:20
-