2010-06-29 11 views
6

Recibo un error al seleccionar de una rows.AsEnumerable(). Estoy utilizando el siguiente código ...Linq y DBNull - Obteniendo el error

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") 


       }); 

mayoría de las veces funciona bien, pero cuando hay nulos en la base de datos que estoy recibiendo este error "no puede lanzar DBNull.Value al tipo 'System.Int16 '. Utilice un tipo que admite nulo. " ¿Cómo puedo corregir esto? No quiero que mis contactos de datos tengan tipos Nullable, me gustaría usar un ternario o algo así, y si un valor es NULL, solo usa 0. ¿Es esto posible?

Gracias por cualquier ayuda,
~ ck

Respuesta

7

Así es como se prueba para los nulos ...

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

Siempre se puede añadir otro método de extensión (no probado):

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

Entonces su sitio de llamada se ve así:

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

me gusta la respuesta de Marc, pero sólo para conseguir otra manera de hacerlo, puede cambiar los tipos de valor para ser anulable (corto? long? etc) y luego se fusionan, por lo que algo así como row.Field ("foo") ?? 0 –

+0

BTW, en lugar de hacer 2 llamadas de fila, si T es siempre un tipo de valor, puede hacer row.Field > (columnName) ?? predeterminado (T) aunque dudo que valga la pena la molestia si también usa tipos de referencia :) –

4

Si su propiedad es anulable, puede hacer esto también;

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

¡respuesta increíble! – DasDas

1

estoy bastante aficionado al operador ??:

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; 
Cuestiones relacionadas