none
Dúvida quanto a objeto de retorno no entity framework RRS feed

  • 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
    segunda-feira, 1 de fevereiro de 2010 20:06

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
    terça-feira, 2 de fevereiro de 2010 13:32
  • 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
    quarta-feira, 3 de fevereiro de 2010 00:02
  • 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
    quarta-feira, 3 de fevereiro de 2010 16:33

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
    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.
    terça-feira, 2 de fevereiro de 2010 12:31
  • 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
    terça-feira, 2 de fevereiro de 2010 13:32
  • Bom dia Henrique, tudo bom amigo? Obrigado pela resposta.

    Você teria um exemplo de como retornar este IList ou o IQueryable para um caso como este meu?

    Vlw pela ajuda.

    Abraços.
    terça-feira, 2 de fevereiro de 2010 13:56
  • 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
    terça-feira, 2 de fevereiro de 2010 16:13
  • 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
    terça-feira, 2 de fevereiro de 2010 16:38
  • 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
    terça-feira, 2 de fevereiro de 2010 16:42
  • Jorge, dei uma olhada no artigo que você me passou, e consegui abrir um pouco mais a idéia. Entretanto, se for possível, vc não poderia demonstrar um pequeno exemplo pra ficar mais claro?

    Vlw mesmo.

    Abraços.
    terça-feira, 2 de fevereiro de 2010 17:28
  • 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
    quarta-feira, 3 de fevereiro de 2010 00:02
  • Ficou bem mais claro agora Jorge.

    Vou fazer uns testes aqui e venho postar dai.

    Vlw mesmo mais uma vez.

    Abraços.
    quarta-feira, 3 de fevereiro de 2010 12:52
  • Boa Sorte Eduardo!

    Se puder marque como resposta! E se tiver mais dúvidas poste aí!!!


    []'s
    Jorge Rua http://jtressino.spaces.live.com http://twitter.com/jtressino
    quarta-feira, 3 de fevereiro de 2010 13:27
  • 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
    quarta-feira, 3 de fevereiro de 2010 16:33
  • Opa Daniel, blz irmão?

    vlw mesmo pela dica, vou tentar implementar as formas que vc descreveu.



    Obrigado a todos pela disposição em ajudar, Jorge, Henrique e Daniel .
    quinta-feira, 4 de fevereiro de 2010 12:21