2012-10-19 12 views
9

Ho una tabella con il seguente formato.Casting String come DateTime in LINQ

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

ho bisogno di recuperare tutti i PID dove Nome iniziano per J e mese di DOB è 10.

nel mio codice, ho recuperare questi in DataTable in C# e poi cercato di utilizzare LINQ per recuperare il risultati che voglio Questo è solo un esempio. Queste etichette potrebbero essere qualsiasi cosa l'utente definisce.

utilizzando LINQ Sono in grado di recuperare tutti i PID in cui il nome inizia con J, ma ogni volta che ho provato a eseguire il cast value per DOB non viene emesso un errore valido. Non riesco a modificare il tipo di colonna nel database poiché Value potrebbe contenere qualsiasi tipo di informazione.

Ecco un pezzo del mio codice. Sono nuovo di LINQ e sto ancora cercando di capirlo.

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

Qual è il valore DateTime di "Jenna"? Non sono sicuro che sia fattibile. – Bobson

risposta

3

Dal momento che non tutti gli elementi nella colonna Valore della tabella sono convertibili a DateTime, quello che hai mancherà sulle conversioni non valide. È possibile aggiungere una clausola che prima controlla che il valore sia DateTime e solo se lo è, lo converte e controlla la proprietà .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"); 

Per potenzialmente migliorare la leggibilità, si potrebbe anche estrarre questo fuori in un metodo separato:

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?); 
} 
+2

Per motivi di leggibilità e "correttezza", credo che sarebbe meglio mettere la logica della data in un metodo separato (DateTime? TryGetDate (valore stringa)) e restituire null se non analizzare ... – ioctlLR

+0

Grazie ad entrambi . Se eseguo semplicemente la query nel modo suggerito da goric su di essa, non si verifica un errore, ma se sto cercando di convertire resultquery in List e fallisce. Se tolgo lo .Mesei il valore == 10, la mia lista funziona correttamente. PID = resultQuery.ToList(); Dove PID è definito al tipo di Lista user1760153

+0

Non solo, ma il tuo codice, come è, non funzionerà. Anche se puoi analizzare la stringa in una data, non puoi semplicemente * lanciarla * su una data, che è ciò che stai facendo qui. – Servy

2

Si sta andando a finire il filtraggio in memoria che non è molto efficiente.

Quindi prima selezionare il tuo dati

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

quindi filtrare sui dati

var filtered = from item in data 
       where item.Label == "Label" 
       && Convert.ToDateTime(item.DOB).Month == 10 
       select item.PID;