Existe-t-il une meilleure façon/plus propre de procéder?
int stockvalue = 0;
if (!Convert.IsDBNull(reader["StockValue"]))
stockvalue = (int)reader["StockValue"];
Le plus court (à mon humble avis) est:
int stockvalue = (reader["StockValue"] as int?) ?? 0;
Explication:
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);
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);
}
}
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.
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.
}
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.
int stockvalue = reader["StockValue"] != DbNull.Value ? Convert.ToInt32(reader["StockValue"]) : 0;
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
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.
utilisez le Nullable<int>
tapez ...int?
pour faire court
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));
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.
int? stockValue = reader["StockValue"] == null || reader["StockValue"] == DBNull.Value ? null : (int?)reader["StockValue"];