Usuário com melhor resposta
filtrar a idade

Pergunta
-
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
-
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
-
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
Todas as Respostas
-
-
-
Silderado
Então seria basicamente isso mesmo.
var dataref = DateTime.now;
Onde essa variável dataref poderia ser passada por parâmetro por exemplo... mas o caminho é por ai mesmo.
var resultado = (from t in MinhaColecao where t.idade > dataref select t);
-
-
-
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
-
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
-
-
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 -
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 -
-
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 -
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 -
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 -
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 -
-
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 -
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
-
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
-
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
-
-
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 -
-
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 -
-
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 -
-
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