none
filtrar a idade RRS feed

Respostas

  • Silderado,

    Segue um exemplo de código abaixo:

    // exemplo de classe pessoa
    class Pessoa
    {
        public string Nome { get; set; }
        public DateTime DataNascimento { get; set; }
    }

    class Tester
    {
        static void Main(string[] args)
        {
            // lista de pessoas
            List<Pessoa> pessoas = new List<Pessoa>()
            {
                new Pessoa { Nome = "Ari C. Raimundo", DataNascimento = new DateTime(1981, 4, 13) },
                new Pessoa { Nome = "Anders Hejlsberg", DataNascimento = new DateTime(1960, 12, 1) },
                new Pessoa { Nome = "Bjarne Stroustrup", DataNascimento = new DateTime(1950, 12, 30) }
            };

            // consulta
            var result = from p in pessoas
                         where CalcularIdade(p.DataNascimento, DateTime.Now) > 30
                         select p;

            // mostra nome das pessoas com mais de 30 anos
            result.ToList<Pessoa>().ForEach(pessoa => Console.WriteLine(pessoa.Nome));
        }

        // método para calcular a idade
        static int CalcularIdade(DateTime dataNascimento, DateTime dataComparacao)
        {
            int anos = dataComparacao.Year - dataNascimento.Year;

            if (dataComparacao.Month < dataNascimento.Month ||
                (dataComparacao.Month == dataNascimento.Month &&
                 dataComparacao.Day < dataNascimento.Day))
                anos--;

            return anos;
        }
    }


    Espero ter ajudado.

    Att.

    Ari C. Raimundo
    • Sugerido como Resposta Ari C. Raimundo sábado, 10 de outubro de 2009 03:31
    • Marcado como Resposta _Rodrigo_ terça-feira, 13 de outubro de 2009 14:23
    • Não Marcado como Resposta _Rodrigo_ terça-feira, 13 de outubro de 2009 15:39
    • Marcado como Resposta _Rodrigo_ terça-feira, 20 de outubro de 2009 15:37
    sábado, 10 de outubro de 2009 03:20
  • Silderado,

    Agora eu entendi, com o ToList() você está realizando o DataBinding do grid com um tipo anônimo, e como você está tentando utilizar a propriedade DataItem, que é um object, não está conseguindo utilizar as colunas do tipo anônimo.

    Minha sugestão é que você realize o cast do seu tipo anônimo utilizando o método abaixo:

    private T CastAnonymousType<T>(T anonymousType, object x)
    {
        return (T)x;
    }


    Assim, no seu evento ItemDataBound é possível fazer assim:

    var result = CastAnonymousType(new { id=0, ds="", ds2=""}, e.Item.DataItem);

    E então é possível ter Intellisense...

    if (result.id == 5)
        ...

    Não sei se essa é a melhor opção, mas é uma maneira de não criar o DataTable.

    Att.

    Ari C. Raimundo
    • Marcado como Resposta _Rodrigo_ terça-feira, 20 de outubro de 2009 15:36
    segunda-feira, 19 de outubro de 2009 18:42
  • Silderado,

    A idéia era transformar o resultado da consulta (IEnumerable<T>) em uma lista genérica e atribuir a mesma como DataSource do seu grid.

    Grid.DataSource = query.ToList();
    Grid.DataBind();


    Assim, o data binding foi realizado com a lista genérica dos tipos anônimos criados na consulta query.

    Minha sugestão foi que no evento ItemDataBound você utilizasse o método para fazer o cast com o tipo anônimo para conseguir então utilizar as propriedades deste.

    var result = CastAnonymousType(new { id=0, ds="", ds2=""}, e.Item.DataItem);

    A parte do código acima somente cria um tipo anônimo qualquer (new { id=X, ds=Y, ds2=Z}) para então converter o DataItem nesse tipo anônimo. É lógico que essa conversão deve ser possível, ou seja, o ideal é criar um tipo anônimo tal qual aquele criado na consulta LINQ.

    Logo, respondendo:

    Utilizando exemplo do filtro que voce passou, como poderia fazer para que o valor retornado no CastAnonymousType seja adicionado na grid?
    Não precisa fazer o cast para adicionar na grid, somente no evento ItemDataBound.

    Vi que adicionou o return(T)x, entretanto tentei adicionar o filtro que voce passou antes mas nao consegui adaptar, substitui o query pelo X, entretanto nao estou conseguindo fazer funcionar...
    A assinatura e o conteúdo do método não mudam, somente adicione o método como um membro do seu formulário ou em uma classe utilitária.

    E como faço quando clicar no botao chamar essa rotina que voce descreveu, do castanonumoustype??
    Conforme expliquei, colocar o método como membro do formulário ou em uma classe utilitária.

    Espero ter ajudado.

    Ari C. Raimundo
    • Marcado como Resposta _Rodrigo_ terça-feira, 20 de outubro de 2009 15:36
    terça-feira, 20 de outubro de 2009 14:34

Todas as Respostas

  • var resultado = (from t in MinhaColecao where t.idade > 18 select t);
    isso?!
    terça-feira, 29 de setembro de 2009 16:34
  • eu tenho a data de nascimento da pessoa e precisava verificar, com base na data atual a idade da pessoa...


    []s
    terça-feira, 29 de setembro de 2009 16:40
  • Silderado

    Então seria basicamente isso mesmo.

    var dataref = DateTime.now;
    var resultado = (from t in MinhaColecao where t.idade > dataref select t);
    Onde essa variável dataref poderia ser passada por parâmetro por exemplo... mas o caminho é por ai mesmo.

    terça-feira, 29 de setembro de 2009 16:52
  • Oi Rodrigo,

    no caso o dataref que eu tenho seria um campo onde colocaria a idade, por exemplo: 30.

    Ai precisaria verificar, no banco de dados, tem ate 30 anos, utilizando a data de nascimento, ex: 10/05/1979, como método de filtro.




    []s
    quarta-feira, 30 de setembro de 2009 15:17
  • alguem?
    []s
    quinta-feira, 1 de outubro de 2009 16:10
  • Silderado,

    Segue um exemplo de código abaixo:

    // exemplo de classe pessoa
    class Pessoa
    {
        public string Nome { get; set; }
        public DateTime DataNascimento { get; set; }
    }

    class Tester
    {
        static void Main(string[] args)
        {
            // lista de pessoas
            List<Pessoa> pessoas = new List<Pessoa>()
            {
                new Pessoa { Nome = "Ari C. Raimundo", DataNascimento = new DateTime(1981, 4, 13) },
                new Pessoa { Nome = "Anders Hejlsberg", DataNascimento = new DateTime(1960, 12, 1) },
                new Pessoa { Nome = "Bjarne Stroustrup", DataNascimento = new DateTime(1950, 12, 30) }
            };

            // consulta
            var result = from p in pessoas
                         where CalcularIdade(p.DataNascimento, DateTime.Now) > 30
                         select p;

            // mostra nome das pessoas com mais de 30 anos
            result.ToList<Pessoa>().ForEach(pessoa => Console.WriteLine(pessoa.Nome));
        }

        // método para calcular a idade
        static int CalcularIdade(DateTime dataNascimento, DateTime dataComparacao)
        {
            int anos = dataComparacao.Year - dataNascimento.Year;

            if (dataComparacao.Month < dataNascimento.Month ||
                (dataComparacao.Month == dataNascimento.Month &&
                 dataComparacao.Day < dataNascimento.Day))
                anos--;

            return anos;
        }
    }


    Espero ter ajudado.

    Att.

    Ari C. Raimundo
    • Sugerido como Resposta Ari C. Raimundo sábado, 10 de outubro de 2009 03:31
    • Marcado como Resposta _Rodrigo_ terça-feira, 13 de outubro de 2009 14:23
    • Não Marcado como Resposta _Rodrigo_ terça-feira, 13 de outubro de 2009 15:39
    • Marcado como Resposta _Rodrigo_ terça-feira, 20 de outubro de 2009 15:37
    sábado, 10 de outubro de 2009 03:20
  • Oi Ari,

    Tive um problema na hora do filtro :(

    Eu nao executo o ToList() no meu result, eu pego as informações que gerou e verifico tambem uma contagem, Result.Count(), entretanto esta ocorrendo o erro: ' Method 'Double CalcularIdade(System.DateTime, System.DateTime)' has no supported translation to SQL.'

    Tem alguma ideia???
     
    • Editado _Rodrigo_ terça-feira, 13 de outubro de 2009 15:41 erro
    terça-feira, 13 de outubro de 2009 14:24
  • Silverado,

    Mostre o seu código aqui no fórum. Eu estei o código que lhe enviei e funcionou normalmente.

    Att.

    Ari C. Raimundo
    terça-feira, 13 de outubro de 2009 18:28
  • Oi Ari,

    Estou fazendo da seguinte forma:


    public void EfetuarFiltro()
    {

        FiltroDataContext db = new FiltroDataContext(StringConect);

        var query = (from P in db.Pessoas
                          
                          where
                          ((CalcularIdade(P.DtNascimento.Value, DateTime.Now) >= 30) && (CalcularIdade(P.DtNascimento.Value, DateTime.Now) <= 45))

                          select new { id = P.Codigo, ds = P.Nome }
                          );

        DataTable DbDados = new DataTable();
        DbDados.Columns.Add("id", typeof(String));
        DbDados.Columns.Add("ds", typeof(String));

        SqlCommand cmd = db.GetCommand(query) as SqlCommand; // O ERRO OCORREU QUANDO CHEGOU NESSA PARTE
        DataTable Tabela = new DataTable();
        SqlDataAdapter adapter = new SqlDataAdapter(cmd);
        adapter.Fill(DbDados);

        Grid.DataSource = DbDados;
        Grid.DataBind();
    }

    // método para calcular a idade
    static int CalcularIdade(DateTime dataNascimento, DateTime dataComparacao)

    {
            int anos = dataComparacao.Year - dataNascimento.Year;

            if (dataComparacao.Month < dataNascimento.Month ||
                (dataComparacao.Month == dataNascimento.Month &&
                 dataComparacao.Day < dataNascimento.Day))
                anos--;

            return anos;
    }


    []s
    terça-feira, 13 de outubro de 2009 19:19
  • Silderado,

    Porque você está utilizando um DataTable? Porque não transforma a sua query em uma lista?

    Grid.DataSource = query.ToList();
    Grid.DataBind();

    O erro vai ocorrer mesmo porque não será possível transformar o método CalcularIdade para o equivalente em SQL.

    Att.

    Ari C. Raimundo
    terça-feira, 13 de outubro de 2009 19:30
  • Oi Ari,

    Eu tenho utiliado o datatable para poder pegar as informações que estao em cada coluna... neste caso como poderia pegar o valor, utilizando ToList() ele demonstra tudo na mesma linha, como retorno as informações que preciso???
    []s
    quinta-feira, 15 de outubro de 2009 12:05
  • Silderado,

    As colunas serão enviadas para o GridView normalmente. Tal como se você estivesse utilizando um DataTable.

    O link abaixo mostra como mostrar somente algumas colunas:

    GridView.Columns Property
    http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.columns.aspx

    Na verdade você terá que fazer isso:

    <columns>
      <asp:boundfield datafield="id" headertext="CabecalhoID"/>
      <asp:boundfield datafield="ds" headertext="CabecalhoDS"/>
    </columns>


    Att.

    Ari C. Raimundo
    quinta-feira, 15 de outubro de 2009 15:49
  • Ari,

     Quanto a isso ok, como faço para saber, no list qual é cada coluna.

     No DataTable eu colocando Dt..Columns["id"] eu sei as informações que tem no id, agora como faço isso no List ??? pq essas informações seriam utilizadas em vários locais
    []s
    quinta-feira, 15 de outubro de 2009 16:59
  • Silderado,

    A query que você criou usando o LINQ cria um tipo anônimo que contém uma propriedade id e outra propriedade ds.

    select new { id = P.Codigo, ds = P.Nome }

    Quando transformamos a variável query para uma lista genérica usando ToList, é criado uma lista genérica contendo objetos desse tipo anônimo. O nome da coluna continua o mesmo (id e ds).

    Por exemplo, se eu quiser mostrar o id e o ds dos objetos retornados da consulta eu faria:

    var listaGenerica = query.ToList();
    foreach(var tipoAnonimo in listaGenerica)
    {
        Console.WriteLine(tipoAnonimo.id);
        Console.WriteLine(tipoAnonimo.ds);
    }


    Att.

    Ari C. Raimundo
    quinta-feira, 15 de outubro de 2009 20:44
  • Oi Ari,

    Eu fiz isso, so que preciso verificar as informações de cada linha que esta no grid em outra função, ou seja, nao tem esse select pq so usei para verificar as informações que queria.

    Quando trabalho com o datatable consigo ver as informações dentro da grid sem problemas, so que com o .ToList() nao to conseguindo, nao divide em colunas as informações, coloca tudo numa mesma linha...

    tem como verificar em coluna?
    []s
    segunda-feira, 19 de outubro de 2009 16:14
  • Silderado,

    Desculpe, não entendi o que você quis dizer com "verificar por coluna" e "colocar tudo na mesma" linha. Pode exemplificar?

    Att.

    Ari C. Raimundo
    segunda-feira, 19 de outubro de 2009 16:31
  • Desculpe Ari, vou tentar ser mais claro :)

    Tenho uma proriedade no grid que é o ItemDataBound que permite verificar todos os dados que estao disponiveis na grid.

    Dentro desta propriedade eu utilizo: System.Data.DataRowView Drv = (System.Data.DataRowView)e.Item.DataItem; para verificar cada linha eu executo var productId = Drv.Row.ItemArray[0]; para pegar a informação da primeira coluna que do datatabel, com isso verifico as informações que preciso.

    Agora, utilizando o ToList() ele me retorna as informações numa mesma linha nao como coluna ex: id = 001;ds = "teste";ds2="teste2"
    []s
    segunda-feira, 19 de outubro de 2009 17:19
  • Silderado,

    Agora eu entendi, com o ToList() você está realizando o DataBinding do grid com um tipo anônimo, e como você está tentando utilizar a propriedade DataItem, que é um object, não está conseguindo utilizar as colunas do tipo anônimo.

    Minha sugestão é que você realize o cast do seu tipo anônimo utilizando o método abaixo:

    private T CastAnonymousType<T>(T anonymousType, object x)
    {
        return (T)x;
    }


    Assim, no seu evento ItemDataBound é possível fazer assim:

    var result = CastAnonymousType(new { id=0, ds="", ds2=""}, e.Item.DataItem);

    E então é possível ter Intellisense...

    if (result.id == 5)
        ...

    Não sei se essa é a melhor opção, mas é uma maneira de não criar o DataTable.

    Att.

    Ari C. Raimundo
    • Marcado como Resposta _Rodrigo_ terça-feira, 20 de outubro de 2009 15:36
    segunda-feira, 19 de outubro de 2009 18:42
  • Oi Ari,

     Seria exatamente isso que voce falou. Ate vi essa questao do anonimo.

     So que fiquei na duvida :(
    (desculpe mas estou começando agora a utilizar o Linq)


    Utilizando exemplo do filtro que voce passou, como poderia fazer para que o valor retornado no CastAnonymousType seja adicionado na grid?

    Vi que adicionou o return(T)x, entretanto tentei adicionar o filtro que voce passou antes mas nao consegui adaptar, substitui o query pelo X, entretanto nao estou conseguindo fazer funcionar...

    E como faço quando clicar no botao chamar essa rotina que voce descreveu, do castanonumoustype??



    poderia me dar mais esse help ???



    []s
    • Editado _Rodrigo_ terça-feira, 20 de outubro de 2009 12:31 adicionado
    terça-feira, 20 de outubro de 2009 12:29
  • Silderado,

    A idéia era transformar o resultado da consulta (IEnumerable<T>) em uma lista genérica e atribuir a mesma como DataSource do seu grid.

    Grid.DataSource = query.ToList();
    Grid.DataBind();


    Assim, o data binding foi realizado com a lista genérica dos tipos anônimos criados na consulta query.

    Minha sugestão foi que no evento ItemDataBound você utilizasse o método para fazer o cast com o tipo anônimo para conseguir então utilizar as propriedades deste.

    var result = CastAnonymousType(new { id=0, ds="", ds2=""}, e.Item.DataItem);

    A parte do código acima somente cria um tipo anônimo qualquer (new { id=X, ds=Y, ds2=Z}) para então converter o DataItem nesse tipo anônimo. É lógico que essa conversão deve ser possível, ou seja, o ideal é criar um tipo anônimo tal qual aquele criado na consulta LINQ.

    Logo, respondendo:

    Utilizando exemplo do filtro que voce passou, como poderia fazer para que o valor retornado no CastAnonymousType seja adicionado na grid?
    Não precisa fazer o cast para adicionar na grid, somente no evento ItemDataBound.

    Vi que adicionou o return(T)x, entretanto tentei adicionar o filtro que voce passou antes mas nao consegui adaptar, substitui o query pelo X, entretanto nao estou conseguindo fazer funcionar...
    A assinatura e o conteúdo do método não mudam, somente adicione o método como um membro do seu formulário ou em uma classe utilitária.

    E como faço quando clicar no botao chamar essa rotina que voce descreveu, do castanonumoustype??
    Conforme expliquei, colocar o método como membro do formulário ou em uma classe utilitária.

    Espero ter ajudado.

    Ari C. Raimundo
    • Marcado como Resposta _Rodrigo_ terça-feira, 20 de outubro de 2009 15:36
    terça-feira, 20 de outubro de 2009 14:34
  • Ajudou sim, e muito... muito obrigado pelo help... vc é o cara do Linq, funcionou certinho...


    []s
    terça-feira, 20 de outubro de 2009 15:36
  • Oi Ari,

    Estou o codigo que voce passou para calcular a idade e esta aparecendo o erro: "Method 'Int32 CalcularIdade(System.DateTime, System.DateTime)' has no supported translation to SQL".

    Codigo: ((CalcularIdade(P.DtNascimento.Value, DateTime.Today) >= 30) && (CalcularIdade(P.DtNascimento.Value, DateTime.Today) <= 45)))

    P.DtNascimento é o campo da tabela

    Sabe o que pode ser???

    []s
    sexta-feira, 30 de outubro de 2009 15:22
  • Silderado,

    Essa foi uma de suas primeiras dúvidas após eu lhe passar o código do método para calcular a idade.

    Att.

    Ari C. Raimundo
    sexta-feira, 30 de outubro de 2009 16:16
  • Oi Ari,

    Realmente esse foi uma das duvidas, entretanto estou fazendo como voce disse e quando tenta executar a Query, por exemplo, para verificar o count (query.ToList().Count()) ocorre o erro neste ponto.


    Tem alguma ideia??


    Estou utilizando uma outra funcao tb no meu filtro, no qual retorna uma string, e apresenta a mesma mensagem ("Method 'System.String Localizar(System.Guid, System.Guid, Double)' has no supported translation to SQL ") neste ponto.


    []s

    []s
    quinta-feira, 3 de dezembro de 2009 12:26
  • ninguem???
    []s
    sexta-feira, 4 de dezembro de 2009 10:10
  • Rodrigo,

    Você não pode fazer essa comparação na consulta de suas entidades pois o EF não consegue traduzir esse método CalcularIdade para o equivalente em SQL.

    Faça a consulta sem esse filtro e, com o resultado da consulta, crie uma lista genérica. Então faça uma outra consulta LINQ nessa lista genérica com o filtro de idade.

    Uma outra opção é criar uma função no banco de dados equivalente à função calcular idade e mapear a mesma no seu modelo.

    Espero ter ajudado.

    Att.

    Ari C. Raimundo
    sexta-feira, 4 de dezembro de 2009 12:46
  • Oi Ari,


    Neste caso a funcao calcular idade, como vc sugeriu na segunda opção criando no banco de dados, ela poderia ser chamada dentro do filtro em linq que estou fazendo ???


    []s
    Rodrigo
    []s
    sexta-feira, 4 de dezembro de 2009 16:00
  • Oi Rodrigo,

    Sim, isso mesmo. Segue alguns links:

    How to: Define a Model with a Stored Procedure (Entity Framework)
    http://msdn.microsoft.com/en-us/library/bb896279.aspx

    How to: Execute a Query Using a Stored Procedure (Entity Framework)
    http://msdn.microsoft.com/en-us/library/bb896334.aspx

    Att.

    Ari C. Raimundo
    sexta-feira, 4 de dezembro de 2009 16:46