2009-08-24 7 views
4

Y at-il une meilleure façon d'écrire ce code ..Y at-il une meilleure façon de le faire: Convert.IsDBNull (ligne [somecolumn]) vérifier

MyObject pymt = new MyObject(); 
pymt.xcol1id= Convert.IsDBNull(row["col1id"]) ? 0 : (int)row["col1id"]; 
pymt.xcold2id= Convert.IsDBNull(row["col2id"]) ? String.Empty : (string)row["col2id"]; 
pymt.xcold3id = Convert.IsDBNull(row["CustNum"]) ? 0 : (decimal)row["xcold3id"]; 

cela pourrait-il être fait d'une manière plus propre .. comme des méthodes génériques, etc.?

+0

double possible de [? Le moyen le plus efficace pour vérifier DBNull puis assigner à une variable] (http://stackoverflow.com/questions/221582/méthode la plus efficace pour vérifier-pour-dbnull -et-then-assign-to-a-variable) – nawfal

Répondre

1
static ToType GenericConvert<ToType>(object value) 
     { 
      ToType convValue = default(ToType); 

      if (!Convert.IsDBNull(value)) 
       convValue = (ToType)value; 

      return convValue; 
     } 


MyObject pymt = new MyObject(); 
pymt.xcol1id= GenericConvert<int>(row["col1id"]); 
pymt.xcold2id= GenericConvert<string>(row["col2id"]) ?? String.Empty; 
pymt.xcold3id = GenericConvert<decimal>(row["CustNum"]); 
+0

Notez que default (string) n'est pas String.Empty, mais null ... – Guffa

+0

@ Guffa, oublié à ce sujet, a corrigé le code. –

0

J'aime vraiment cela. Notre équipe utilisait des instructions if/else qui sont plus difficiles à lire à mon avis.

if (row["col1id"] == dbnull.value) 
    pymt.xcol1id = 0; 
else 
    pymt.xcol1id = (int)row["col1id"]; 

Votre code est plus facile à lire car il place chaque affectation sur des lignes individuelles.

Une fonction telle que suggérée par Stan peut raccourcir les lignes, mais elle cache le fait que les valeurs nulles sont remplacées à moins que vous ne lui donniez un nom très bavard.

8

Vous pourriez faire des méthodes d'extension génériques comme ceci:

public static class DataRowExtensions { 

    public static T GetValueOrDefault<T>(this DataRow row, string key) { 
     return row.GetValueOrDefault(key, default(T)); 
    } 

    public static T GetValueOrDefault<T>(this DataRow row, string key, T defaultValue) { 
     if (row.IsNull(key)) { 
     return defaultValue; 
     } else { 
     return (T)row[key]; 
     } 
    } 

} 

Utilisation:

MyObject pymt = new MyObject(); 
pymt.xcol1id = row.GetValueOrDefault<int>("col1id"); 
pymt.xcold2id = row.GetValueOrDefault<string>("col2id", String.Empty); 
pymt.xcold3id = row.GetValueOrDefault<int>("CustNum"]); 
+0

doh! me battre au coup de poing. – Brannon

+0

+1 votre implémentation est meilleure que la mienne, j'adresse la mienne pour réparer ce que vous avez mentionné. mais maintenant il semble sale :( –

+0

J'ai décidé d'utiliser cette approche parce que j'utilise VS2005, version .net 2.0 Merci à tous pour votre contribution, je l'apprécie beaucoup ... –

5

J'ai tendance à utiliser l'opérateur coalescent null dans des situations comme celles-ci. En outre, DBNull.ToString renvoie string.Empty, vous n'avez donc rien à faire de fantaisie.

MyObject pymt = new MyObject(); 
pymt.xcol1id= row["col1id"] as int? ?? 0; 
pymt.xcold2id= row["col2id"].ToString(); 
pymt.xcold3id = row["CustNum"] as decimal? ?? 0; 
+1

+1 J'allais écrire cela au départ , mais a décidé d'écrire un GenericConvert. –

+0

Cela ne fonctionnera pas si la propriété que vous définissez est un int et non un int? est-ce que cela va? –

+0

ce sera le cas, car le compilateur se rend compte qu'il n'y a aucun moyen qu'une valeur nulle sera définie. –

0

Quelques alternatives que je peux penser rapidement:

  1. jeux de données
  2. Utilisez les lecteurs de SqlTypes comme ReadSqlInt32 fortement typé en commun: ce INullable.
  3. Générez le code avec la transformation XSLT à partir de XML, de sorte que le code de vérification est facile à modifier et à maintenir.
2

Mieux encore, l'ajouter comme une méthode d'extension à l'DataRow:

static T GetValueOrDefault<T>(this DataRow row, string columnName) 
{ 
    if (!row.IsNull(columnName)) 
    { 
     // Might want to support type conversion using Convert.ChangeType(). 
     return (T)row[columnName] 
    } 

    return default(T); 
} 

Vous pouvez l'utiliser comme:

pymt.xcol1id = row.GetValueOrDefault<int>("col1id"); 
pymt.xcol2id = row.GetValueOrDefault<string>("col2id"); 
pymt.xcol3id = row.GetValueOrDefault<decimal>("col3id"); 
+0

Notez que la valeur par défaut (chaîne) n'est pas String.Empty, mais null ... – Guffa

+0

Bon point. Votre réponse est plus complète, mieux vaut voter pour votre réponse que pour ajouter au bruit. – Brannon

5

Absolument, il y a un moyen plus propre d'écrire ce code si vous utilisez re.NET 3.5, et sans réinventer les méthodes d'extension que Microsoft a déjà écrit pour vous. Il suffit d'ajouter une référence à System.Data.DataSetExtensions.dll, et vous serez en mesure de le faire:

MyObject pymt = new MyObject 
       { 
        xcol1id = row.Field<int?>("col1id") ?? 0, 
        xcol2id = row.Field<string>("col2id") ?? String.Empty, 
        xcol3id = row.Field<decimal?>("col3id") ?? 0M 
       }; 
Questions connexes