2012-10-19 13 views
9

Mam tabelę o następującym formacie.Casting String jako DateTime w LINQ

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

muszę pobrać wszystkie PID gdzie Imię zaczynające się na literę J i miesiąc DOB jest 10.

w moim kodu, odzyskać je w DataTable w C#, a następnie próbował użyć LINQ aby pobrać wyniki, które chcę. To tylko przykład. Etykiety te mogą być dowolnie zdefiniowane przez użytkownika.

za pomocą LINQ Jestem w stanie odzyskać wszystkie PID, w których imię zaczyna się od J, ale za każdym razem, gdy próbowałem uzyskać wartość Cast dla DOB, otrzymuję nieprawidłowy błąd rzucania. Nie mogę zmienić typu kolumny w bazie danych, ponieważ wartość może zawierać dowolny rodzaj informacji.

Oto fragment mojego kodu. Jestem nowy w LINQ i wciąż staram się rozgryźć.

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

Jaka jest wartość DateTime z "Jenna"? Nie jestem pewien, czy to możliwe. – Bobson

Odpowiedz

3

Ponieważ nie wszystkie pozycje w kolumnie Wartość stołu są wymienialne na DateTime, co masz nie powiedzie się na nieprawidłowych konwersji. Możesz dodać klauzulę, która najpierw sprawdza, czy wartość jest równa DateTime i tylko jeśli jest, konwertuje ją i sprawdza właściwość .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"); 

Aby potencjalnie poprawić czytelność, można także wyodrębnić ten się do osobnego sposobu:

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

Ze względu na czytelność i "poprawność" uważam, że lepiej byłoby umieścić logikę daty w osobnej metodzie (DateTime? TryGetDate (wartość ciągu)) i zwrócić wartość null, jeśli nie można parsować ... – ioctlLR

+0

Dziękuję wam obu . Jeśli po prostu uruchomię zapytanie w sposób sugerowany przez Gorica, nie powoduje to błędu, ale jeśli próbuję przekonwertować wynik kwerendy na List i nie powiedzie się. Jeśli wyjmę .Month == 10, moja lista działa poprawnie. PID = resultQuery.ToList(); Gdzie PID jest zdefiniowany w rodzaju listy user1760153

+0

Nie tylko to, ale twój kod, jak to nie będzie działać. Nawet jeśli możesz przeanalizować ciąg znaków do daty, nie możesz po prostu * rzucić * go na datę, co właśnie tutaj robisz. – Servy

2

Idziesz do końca się filtrowanie w pamięci, która nie jest bardzo skuteczny.

więc najpierw wybrać swoje dane

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

następnie przesączyć na danych

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