web-dev-qa-db-fra.com

Gérer DBNull en C #

Existe-t-il une meilleure façon/plus propre de procéder?

int stockvalue = 0;
if (!Convert.IsDBNull(reader["StockValue"]))
    stockvalue = (int)reader["StockValue"];
39
Andreas

Le plus court (à mon humble avis) est:

int stockvalue = (reader["StockValue"] as int?) ?? 0;

Explication:

  • Si reader ["StockValue"] est de type int, la valeur sera retournée et le "??" l'opérateur retournera le résultat
  • Si reader ["StockValue"] n'est PAS de type int (par exemple DBNull), null sera renvoyé et le "??" L'opérateur renverra la valeur 0 (zéro).
60
Philippe Leybaert

La façon dont je gère cela est

int? stockvalue = reader["StockValue"] as int?;

Très simple, propre et une seule ligne. Si, pour une raison quelconque, je ne peux absolument pas avoir une valeur nulle (ce que je trouve généralement mal raisonné car je préfère savoir si une valeur a un sens ou si elle a été unialisée pour un type primitif), je ferais:

int stockvalue = (reader["StockValue"] as int?).GetValueOrDefault(-1);
29
Chris Marisic

J'ai écrit une méthode d'extension il y a plusieurs jours. En l'utilisant, vous pourriez simplement faire:

int? stockvalue = reader.GetValue<int?>("StockValue");

Voici la méthode d'extension (modifiez en fonction de vos besoins):

public static class ReaderHelper
{
    public static bool IsNullableType(Type valueType)
    {
        return (valueType.IsGenericType &&
            valueType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)));
    }

    public static T GetValue<T>(this IDataReader reader, string columnName)
    {
        object value = reader[columnName];
        Type valueType = typeof(T);
        if (value != DBNull.Value)
        {
            if (!IsNullableType(valueType))
            {
                return (T)Convert.ChangeType(value, valueType);
            }
            else
            {
                NullableConverter nc = new NullableConverter(valueType);
                return (T)Convert.ChangeType(value, nc.UnderlyingType);
            }
        }
        return default(T);
    }
}
11
Vivek
int? stockvalue = (int?)(!Convert.IsDBNull(result) ? result : null);

Une solution possible pour que vous vous assuriez que le DBNull est transmis à votre code. Pour notre groupe, comme meilleure pratique, nous essayons de ne pas autoriser les colonnes NULL dans la base de données à moins que ce ne soit vraiment nécessaire. Il y a plus de frais généraux dans le codage pour le gérer, et parfois simplement repenser le problème le rend si inutile.

10
Digicoder

Oui, vous pouvez utiliser int? De cette façon, vous pouvez avoir une valeur par défaut de null au lieu de 0. Étant donné que le résultat de la valeur de stock peut potentiellement être 0, il n'y a pas de confusion quant à savoir si la base de données était 0 ou nulle. Par exemple, comme ceci (pré nullable), nous avons eu une initialisation par défaut de -1 pour représenter qu'aucune valeur n'a été affectée. Personnellement, je pensais que c'était un peu dangereux car si vous oubliez de le régler sur -1, il y a un problème de corruption de données qui peut être très difficile à détecter.

http://msdn.Microsoft.com/en-us/library/2cf62fcy (VS.80) .aspx

int? stockvalue = null;

if (!Convert.IsDBNull(reader["StockValue"]))
    stockvalue = (int)reader["StockValue"];

//Then you can check 

if(stockValue.HasValue)
{
  // do something here.
}
7
kemiller2002

Bien qu'il soit pratique de référencer reader["StockValue"], ce n'est pas très efficace. Il n'est pas non plus fortement typé, car il renvoie le type object.

Au lieu de cela, dans votre code, faites quelque chose comme ceci:

int stockValueOrdinal = reader.GetOrdinal("StockValue");
int? stockValue = reader.IsDbNull(stockValueOrdinal) ?
    null : 
    reader.GetInt32(stockValueOrdinal);

Bien sûr, il est préférable d'obtenir tous les ordinaux en même temps, puis de les utiliser dans le code.

6
John Saunders
int stockvalue = reader["StockValue"] != DbNull.Value ? Convert.ToInt32(reader["StockValue"]) : 0;
3
amin10043

Voici une façon.

int stockvalue = Convert.IsDbNull(reader["StockValue"]) ? 0 : (int)reader["StockValue"];

Vous pouvez également utiliser TryParse

int stockvalue = 0
Int32.TryParse(reader["StockValue"].ToString(), out stockvalue);

Faites-nous savoir quel chemin fonctionne pour vous

1
sidney.andrews

Vous pouvez effectuer cette conversion directement dans votre requête DB, évitant ainsi tous les cas particuliers.

Mais je n'appellerais pas cela "plus propre", à moins que vous ne puissiez utiliser systématiquement ce formulaire dans votre code, car vous perdriez des informations en renvoyant "0" au lieu de NULL à partir de la base de données.

1
lexu

utilisez le Nullable<int> tapez ...int? pour faire court

0
Rich

J'ai deux méthodes d'extension suivantes dans mon projet:

    public static T GetValueSafe<T>(this IDataReader dataReader, string columnName, Func<IDataReader, int, T> valueExtractor)
        where T : class 
    {
        T value;
        if (dataReader.TryGetValueSafe(columnName, valueExtractor, out value))
        {
            return value;
        }

        return null;
    }

    public static bool TryGetValueSafe<T>(this IDataReader dataReader, string columnName, Func<IDataReader, int, T> valueExtractor, out T value)
    {
        int ordinal = dataReader.GetOrdinal(columnName);

        if (!dataReader.IsDBNull(ordinal))
        {
            // Get value.
            value = valueExtractor.Invoke(dataReader, ordinal);

            return true;
        }

        value = default(T);
        return false;
    }

L'utilisation peut être comme ceci:

string companyName = dataReader.GetValueSafe("CompanyName", (reader, ordinal) => reader.GetString(ordinal));
0
Andrew Bezzub

Pas vraiment. Vous pouvez l'encapsuler dans une méthode:

public int getDBIntValue(object value, int defaultValue) {
  if (!Convert.IsDBNull(value)) {
    return (int)value;
  }
  else {
    return defaultValue;
  }

Et appelez-le comme ceci:

stockVaue = getDBIntVaue(reader["StockValue"], 0);

Ou vous pouvez utiliser coalesce dans votre requête pour forcer la valeur retournée à être non nulle.

Modifier - erreurs de code muet corrigées sur la base des commentaires reçus.

0
Ray
int? stockValue = reader["StockValue"] == null || reader["StockValue"] == DBNull.Value ? null : (int?)reader["StockValue"];
0
Will Marcouiller