Casting String como DateTime no LINQ

9

Eu tenho uma tabela com o seguinte formato.

PID     ID       Label        Value
------------------------------------------
1       1        First Name    Jenna
1       2        DOB           10/12/1980

Eu preciso recuperar todos os PIDs onde o primeiro nome que começa com J e o mês de DOB é 10.

no meu código, eu recupero estes em DataTable em C # e, em seguida, tentei usar o LINQ para recuperar os resultados desejados. Este é apenas um exemplo. Esses rótulos podem ser qualquer coisa que o usuário definir.

usando LINQ Eu sou capaz de recuperar todos os PIDs onde o primeiro nome começa com J, mas toda vez que eu tentei converter o valor para o DOB eu recebo um erro não válido. Não consigo alterar o tipo de coluna no banco de dados, pois o valor pode conter qualquer tipo de informação.

Aqui está uma parte do meu código. Eu sou novo no LINQ e ainda estou tentando descobrir isso.

var resultQuery = from r in query.AsEnumerable()
where (r.Field<string>("Label") == Label  &&
r.Field<DateTime>("Value").Month == 10)
select r.Field<int>("PID");
    
por user1760153 19.10.2012 в 20:16
fonte

2 respostas

3

Como nem todos os itens na coluna Valor da tabela são conversíveis em DateTime , o que você terá falhará em conversões inválidas. Você pode adicionar uma cláusula que primeiro verifique se o valor é DateTime e, somente se estiver, converte-o e verifica a propriedade .Month .

DateTime d;
var resultQuery = from r in query.AsEnumerable()
                  where (r.Field<string>("Label") == Label &&
                      DateTime.TryParse(r.Field<string>("Value"), out d) && 
                      d.Month == 10)
                  select r.Field<int>("PID");

Para melhorar a legibilidade, você também pode extrair isso em um método separado:

var resultQuery = from r in query.AsEnumerable()
                  let d = TryGetDate(r.Field<string>("Value"))
                  where (r.Field<string>("Label") == Label &&
                      d != null && 
                      d.Month == 10)
                  select r.Field<int>("PID");

private DateTime? TryGetDate(string value)
{
    DateTime d;
    return DateTime.TryParse(value, out d) ? d : default(DateTime?);
}
    
por goric 19.10.2012 / 20:21
fonte
2

Você vai acabar filtrando na memória, o que não é muito eficiente.

Então, primeiro selecione seus dados

var data= from r in query.AsEnumerable();

Em seguida, filtre os dados

var filtered = from item in data
               where item.Label == "Label"
               && Convert.ToDateTime(item.DOB).Month == 10
               select item.PID;
    
por Robin V. 19.10.2012 / 20:31
fonte