C# - Dynamic Type do Concrete Type

69 views
Skip to first unread message

Andrew Paes

unread,
Oct 16, 2013, 3:30:45 PM10/16/13
to de...@googlegroups.com
Boa tarde Pessoal,

Bom, procurei no Google nos últimos dias alguma maneira de fazer o seguinte, em C#:

Tenho uma método DinamicoParaConcreto ( digamos assim, irei usar nome simples ) que recebe um parâmetro "string nomeTabela". Dentro desse método quero, utilizando essa string que tem o nome da tabela "TB_Usuario", quero fazer uma consulta LINQ qualquer. Para tal, preciso fazer uma conversão ( encontrar e converter ) a string no objeto do Entity. Usei reflection para isso, mas chega um dado momento que não consigo pegar as propriedades do objeto porque o objeto é dinâmico, tentando fazer um cast por ChangeType não dá porque o objeto ainda não tem implementado o IConvertible.

Alguém tem algum exemplo de como fazer isso?

Alguém em algum lugar já deve ter feito consulta dinâmica usando LINQ e EF. :) ( espero que sim )

Abraço e obrigado,
--
Andrew Paes
+555192812162

Filipe Calleya Beis

unread,
Oct 16, 2013, 4:06:10 PM10/16/13
to de...@googlegroups.com
Tenho uma pergunta em cima disso,
Caso você consiga criar a instancia em cima da string passada, como tu pretende fazer a consulta dinâmica se cada entidade possui suas propriedades (colunas) especificas?

Caso esse problema tu já tenha solucionado, queria saber o seguinte, por que tu diz isso:
"mas chega um dado momento que não consigo pegar as propriedades do objeto porque o objeto é dinâmico", como tu fez o EF criar as classes da Base de dados?
Estou perguntando isso pois eu uso o EF direto e da maneira que eu configuro eles cria as minhas classes e maneira não dinâmica e sim físicas mesmo. Tu esta utilizando os template (.tt) é isso?

Abraço,

Beis



2013/10/16 Andrew Paes <andre...@gmail.com>
--
--
--
Acesse nosso blog http://devrs.net/
Siga-nos no twitter! http://twitter.com/DevRsNet
--
Antes de criar um novo post, para maior organização do grupo, procure seguir as regras de TAGS: http://devrs.net/regras-da-lista
Para postar para o grupo, envie email para de...@googlegroups.com
Para sair do grupo, envie email para devrs+un...@googlegroups.com
 
---
Você está recebendo esta mensagem porque se inscreveu no grupo "DevRS.NET" dos Grupos do Google.
Para cancelar a inscrição neste grupo e parar de receber seus e-mails, envie um e-mail para devrs+un...@googlegroups.com.
Para obter mais opções, acesse https://groups.google.com/groups/opt_out.



--
Filipe Calleya Beis
Arquiteto de Software
cal...@gmail.com

Jackson de Fraga

unread,
Oct 16, 2013, 5:40:53 PM10/16/13
to de...@googlegroups.com

Você quer passar o nome da tabela e retornar uma instância?

--

Cristian Mathias

unread,
Oct 16, 2013, 6:59:50 PM10/16/13
to de...@googlegroups.com

Bernardo Bosak de Rezende

unread,
Oct 16, 2013, 7:21:32 PM10/16/13
to de...@googlegroups.com
Seguindo a linha de pensamento do Jackson avalie se não seria interessante implementar um repositório genérico.

Leitura de Unity of Work + Generic Repository:



Stay sharp!




2013/10/16 Cristian Mathias <cristian...@gmail.com>



--
Bernardo Bosak de Rezende
http://bernardorezende.net/ - Arquitetura e Desenvolvimento
https://github.com/bernardobrezende/ - GitHub

"The weather-cock on the church spire, though made of iron, would soon be broken by the storm-wind if it did not understand the noble art of turning to every wind."
Heinrich Heine

Filipe Calleya Beis

unread,
Oct 16, 2013, 7:42:14 PM10/16/13
to de...@googlegroups.com
Fala Andrew,

Acho que entendi o que tu precisa, só me responde o que perguntei por favor!

De: Bernardo Bosak de Rezende
Enviada em: ‎16/‎10/‎2013 20:21
Para: de...@googlegroups.com
Assunto: Re: [DevRS.NET] C# - Dynamic Type do Concrete Type

Diogo Lucas

unread,
Oct 16, 2013, 9:20:06 PM10/16/13
to de...@googlegroups.com
Tem uma frase boa sobre expressões regulares, mais ou menos assim: "I decided to use regular expressions to solve a problem. Now I have two problems."

O mesmo poderia ser dito sobre reflection -- a probabilidade de abuso da ferramenta é sempre alta e isso pode gerar código pouco performático, instável e de difícil manutenção.

Sendo assim, se teu problema é para implementar um código que vai ser posto em produção, recomendo uma olhada nas sugestões do Bernardo, por exemplo.

Agora, se o objetivo é aprendizado ou apenas diversão (sim, nerd do bom se diverte com isso), que tal nos passares alguns exemplos de como seriam as chamadas para esse código, para tentarmos pensar numa solução?

[]s

Diogo


2013/10/16 Filipe Calleya Beis <cal...@gmail.com>
Fala Andrew,

Acho que entendi o que tu precisa, só me responde o que perguntei por favor!
Enviada em: 16/10/2013 20:21

Filipe Calleya Beis

unread,
Oct 16, 2013, 9:50:18 PM10/16/13
to de...@googlegroups.com
Digamos que concordo em gênero numero e grau com o Diogo, não sei o que queres fazer, mas tenho certeza que Reflection não é a solução.

De: Diogo Lucas
Enviada em: ‎16/‎10/‎2013 22:20

Jackson de Fraga

unread,
Oct 16, 2013, 10:38:28 PM10/16/13
to de...@googlegroups.com

Teríamos que descobrir a real necessidade, porque passar uma string e retornar um objeto ou lista de objeto me parece um pouco maluco...
As vezes pensamos em algo que talvez já exista de forma um pouco semelhante mas atende a necessidade.

Andrew Paes

unread,
Oct 17, 2013, 9:26:18 AM10/17/13
to de...@googlegroups.com
Bom dia pessoal,

Desculpem pela demora, mas não tive como responder ontem a noite, pois estava em aula da faculdade. Antes de tudo, obrigado pelo auxílio e pela disposição.

Ainda não li todos os fóruns que me enviaram, vou dar uma lida com calma.

Respondendo a pergunta do Beis;Sim, uso o .tt.

Jackson, o objetivo é passar por parâmetro (string nomeTabela, string[] camposRetorno, string[] camposConsulta), resumidamente é isso. A partir disso, utilizar os parâmetros e montar uma consulta.

Já olhei este fórum http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx  e dele veio a base ( com a ajuda de outo amigo ) para montar a cláusula dinamicamente ( sendo montada por POST, pois por GET também testamos), segue abaixo:

DataRequest
Table Table
Filter Filter

Table
string Name
List<string> Fields

Filter
string Field
string Operator                //operador, ex: -eq, -neq, -gt, -gte, -lt, -lte, -startswith, -endswith
string Logic                     //and ou or
object Value
List<Filter> Filters

Seguindo essa mesma estrutura de classes em JSON, tu poderias postar para o servidor a mesma busca da seguinte forma:

table : { name : "TB_USUARIO", fields : [ "USERNAME", "E_MAIL_USU" ]  }, filter : { field : "COD_PES", operator : "eq", logic : "and", value : "123" } }

Meu problema, não está sendo montar a cláusula e sim especificar em qual tabela essa consulta vai ser feita.

Bom  Diogo, certamente me divirto com isso, mas nesse momento não é só diversão hehehehe, tentei resumir ao máximo o trecho de código para tentar facilitar o que preciso, coloquei em anexo num .DOC para manter as cores e indentação do código.

Abraço,


2013/10/16 Jackson de Fraga <jackson...@gmail.com>



--
Andrew Paes
+555192812162
snippet.docx

Cristian Mathias

unread,
Oct 17, 2013, 12:20:09 PM10/17/13
to de...@googlegroups.com
Nesse caso não seria melhor usar o executeStoreQuery? 

string sql = "select * from pessoa where nome = @Nome";

var args = new DbParameter[] { new SqlParameter { ParameterName = "Nome", Value = "João" } };

context.ExecuteStoreQuery<Student>(sql, args)

Ou retornando um dynamic:

fonte: http://msdn.microsoft.com/en-us/library/vstudio/bb738512(v=vs.100).aspx

using (AdventureWorksEntities context =
    new AdventureWorksEntities())
{
    string myQuery = @"SELECT p.ProductID, p.Name FROM 
        AdventureWorksEntities.Products as p";

    foreach (DbDataRecord rec in
        new ObjectQuery<DbDataRecord>(myQuery, context))
    {
        Console.WriteLine("ID {0}; Name {1}", rec[0], rec[1]);
    }
}

Andrew Paes

unread,
Oct 18, 2013, 1:43:29 PM10/18/13
to de...@googlegroups.com
Opa pesoal,

Consegui progredir, consegui fazer a consulta dinamicamente usando Dynamics ( redundante isso ), porém ainda não atingi o objetivo que quero. Fui usando as dicas desse fórum, o primeiro para Dynamics e o segundo para o LINQ to SQL:



Porém, seguindo pela linha de LINQ to SQl, encontrei algumas restrições, e a uma delas me faz toda a falta, o LazyLoad. Digo isso porque o LINQ to SQl só faz o Lazyload se for com um banco SQL Server, usando os templates .tt, e ese não é meu caso, uso um Oracle 11g.


Segue parte do código usando o LINQ to SQL ( coloquei parte da consulta hardcoded, p/ facilitar a leitura )

/*##################*/
tring tableName = "TB_USUARIO";

            ObjectHandle handle = Activator.CreateInstance("DCEngine", string.Format("DCEngine.Entity.{0}", tableName)); // Nova instancia do objeto
            Type typeEntityObject = handle.Unwrap().GetType();

            var dbType = this._DB.GetType();
            var dbProp = this._DB.GetType().GetProperty(tableName); // Vindo diretamente do .tt do EF
            var entityObject = dbProp.GetValue(this._DB); // Objeto sem os atributos da tabela

            DbSet dsEntity = this._DB.Set(typeEntityObject);

            var x = dsEntity.AsQueryable().Where("COD_PES=11717").Select("USERNAME");
/*#############*/

Esta consulta tem relacionamento com outras tabelas, e o retorno não traz as referencias (objeto)da outra tabela, traz como singleObject somente.

Fiz o gol, mas foi marcado impedimento. =/

Minha tentativa agora é transformar o DbSet em um Entity, acho que é minha salvação.

Obrigado pela atenção de todos, abraço,


2013/10/17 Cristian Mathias <cristian...@gmail.com>



--
Andrew Paes
+555192812162

Andrew Paes

unread,
Oct 22, 2013, 12:15:33 PM10/22/13
to de...@googlegroups.com
Pesssoal,

Consegui fazer o que queria, obrigado pela ajuda e pelos fóruns indicados.

Assim que estiver totalmente concluído o projeto, compartilharei com vocês.

Mas agora tenho uma pendenga ainda. Usando as referências desse tutorial, estou empacado em um ponto.


Quando faço a consulta abaixo, consigo manter todos os relacionamentos certinho.

IQueryable resultSet = this._DsEntity.AsQueryable().Where("SEQ_SETOR = 123").Select("new (USERNAME, TB_PESSOA.TB_TELEFONE)");"


A linha acima me retorna corretamente, porém eu gostaria que ao invés de retornar a todos os campos da tabela TB_TELEFONE (que pode ser mais de 1 por pessoa) eu gostaria de apenas alguns, porém não estou conseguindo informar essa especialização de retorno, quando quero especificar um campo de uma tabela (referencia como ICollection), ele me dá erro.

IQueryable resultSet = this._DsEntity.AsQueryable().Where("SEQ_SETOR = 123").Select("new (USERNAME, TB_PESSOA.TB_TELEFONE.NUM_TELPES)");"


A tabela "principal" possui alguns relacionamentos como por exemplo: TB_USUARIO > TB_PESSOA > TB_TELEFONE

Abraço,


2013/10/18 Andrew Paes <andre...@gmail.com>



--
Andrew Paes
+555192812162
Reply all
Reply to author
Forward
0 new messages