2010-06-29 18 views
6

Otrzymuję błąd podczas wybierania z wiersza.Aby liczba(). Używam następujący kod ...Linq i DBNull - błąd podczas odbierania

var rows = ds.Tables[0].AsEnumerable(); 
       trafficData = rows.Select(row => new tdDataDC 
       { 
        CalculationCount = row.Field<Int64>("biCalculationCountSeqID") 
        , Zone = row.Field<Int16>("siFkZoneId") 
        , Miles = row.Field<decimal>("dcMiles") 
        , Plaza = row.Field<Int16>("siFkPlazaId") 
        , VehicleCount = row.Field<int>("iVehicleCount") 


       }); 

Większość czasu to działa dobrze, ale kiedy są wartości null w bazie danych dostaję ten błąd „nie można rzutować DBNull.Value wpisać„System.Int16 "Proszę użyć typu zerowego." Jak mogę to poprawić? Nie chcę, aby moje datacontracts miały typy Nullable, chciałbym użyć potrójnego lub coś takiego, a jeśli wartość jest równa NULL, wystarczy użyć 0. Czy to możliwe?

Dzięki za wszelką pomoc,
~ ck

Odpowiedz

7

Oto jak przetestować dla wartości null ...

Plaza = row.IsNull("siFkPlazaId") ? 0 : row.Field<int>("siFkPlazaId") 
11

Zawsze możesz dodać inną metodę rozszerzenia (niesprawdzone):

public static T FieldOrDefault<T>(this DataRow row, string columnName) 
    { 
     return row.IsNull(columnName) ? default(T) : row.Field<T>(columnName); 
    } 

Następnie twój callsite wygląda następująco:

var rows = ds.Tables[0].AsEnumerable(); 
       trafficData = rows.Select(row => new tdDataDC 
       { 
        CalculationCount = row.FieldOrDefault<Int64>("biCalculationCountSeqID") 
        , Zone = row.FieldOrDefault<Int16>("siFkZoneId") 
        , Miles = row.FieldOrDefault<decimal>("dcMiles") 
        , Plaza = row.FieldOrDefault<Int16>("siFkPlazaId") 
        , VehicleCount = row.FieldOrDefault<int>("iVehicleCount") 


       }); 
+1

Lubię odpowiedź Marca, ale po prostu dostać inny sposób to zrobić, można zmienić typy wartość do pustych (krótka? długo? itp.), a następnie łączą się, więc coś jak wiersz.Field ("foo")? 0 –

+0

BTW, zamiast wykonywać 2 wiersze wywołań, jeśli T jest zawsze typu wartości, można zrobić wiersz.Field > (columnName)? domyślnie (T), chociaż wątpię, czy warto mieć kłopot, jeśli używasz również typów referencyjnych :) –

4

Jeśli twoja własność jest zerowa, możesz to również zrobić;

Plaza = row.Field<int16?>("siFkPlazaId") 
+0

wspaniała odpowiedź! – DasDas

1

Jestem bardzo lubiący operatora ??:

CalculationCount = row.Field<Int64?>("biCalculationCountSeqID") ?? 0 
       , Zone = row.Field<Int16?>("siFkZoneId") ?? 0 
       , Miles = row.Field<decimal?>("dcMiles") ?? 0.0m 
       , Plaza = row.Field<Int16?>("siFkPlazaId") ?? 0 
       , VehicleCount = row.Field<int>("iVehicleCount") 0;