2010-06-29 3 views
6

Je reçois une erreur lors de la sélection d'un rows.AsEnumerable(). J'utilise le code suivant ...Linq et DBNull - Erreur d'obtention

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


       }); 

La plupart du temps, il fonctionne bien, mais quand il y a NULLS dans la base de données que je reçois cette erreur « ne peut pas lancer DBNull.Value taper « System.Int16 Veuillez utiliser un type NULL. " Comment puis-je corriger cela? Je ne veux pas que mes contrats de données aient des types Nullable, j'aimerais utiliser un ternaire ou quelque chose, et si une valeur est NULL, utilisez simplement 0. Est-ce possible?

Merci pour toute aide,
~ ck

Répondre

7

Voici comment tester pour ... nulls

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

Vous pouvez toujours ajouter une autre méthode d'extension (non testé):

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

Votre site d'appel ressemble à:

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

J'aime la réponse de Marc, mais juste pour obtenir une autre façon de le faire, vous pouvez changer les types de valeur à annulable (courte? long? etc), puis coalesce, donc quelque chose comme row.Field ("foo") ?? 0 –

+0

BTW, plutôt que de faire 2 appels de ligne, si T est toujours un type de valeur, vous pouvez faire row.Field > (columnName) ?? par défaut (T) bien que je doute que cela en vaille la peine si vous utilisez aussi des types de référence :) –

4

Si votre propriété est nullable, vous pouvez le faire également;

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

awesome answer! – DasDas

1

Je suis assez friand de l'opérateur ??:

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;