これを行うためのより良い/きれいな方法はありますか?
int stockvalue = 0;
if (!Convert.IsDBNull(reader["StockValue"]))
stockvalue = (int)reader["StockValue"];
最短(IMHO)は次のとおりです。
int stockvalue = (reader["StockValue"] as int?) ?? 0;
説明:
私がこれを扱う方法は
int? stockvalue = reader["StockValue"] as int?;
非常にシンプルでクリーンな1行。何らかの理由で絶対にnull値を持つことができない場合(値に意味があるかどうか、またはプリミティブ型に対してユニット化されているかどうかを知りたいので、通常は不十分な推論を見つけます):
int stockvalue = (reader["StockValue"] as int?).GetValueOrDefault(-1);
数日前に拡張メソッドを書きました。それを使用することで、あなたはただすることができます:
int? stockvalue = reader.GetValue<int?>("StockValue");
拡張メソッドは次のとおりです(ニーズに合わせて変更します)。
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);
DBNullがコードに引き継がれるようにするための1つの可能な解決策。私たちのグループでは、ベストプラクティスとして、本当に必要でない限り、データベースでNULL列を許可しないようにします。それを処理するためのコーディングにはより多くのオーバーヘッドがあり、場合によっては問題を再考するだけで不要になることがあります。
はい、int?
を使用できます。この方法では、デフォルト値を0ではなくnullにすることができます。stockvalueの結果は0になる可能性があるため、データベースが0であるかnullであるかについて混乱はありません。たとえば、このような(事前NULL可能)には、値が割り当てられなかったことを表すデフォルトの初期化-1がありました。個人的には、-1に設定するのを忘れると、追跡するのが本当に難しいデータ破損の問題があるため、これは少し危険だと思いました。
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.
}
reader["StockValue"]
を参照するのは便利ですが、あまり効率的ではありません。型object
を返すため、厳密に型指定されていません。
代わりに、コード内で次のようなことを行います。
int stockValueOrdinal = reader.GetOrdinal("StockValue");
int? stockValue = reader.IsDbNull(stockValueOrdinal) ?
null :
reader.GetInt32(stockValueOrdinal);
もちろん、すべての序数を一度に取得し、コード全体で使用することをお勧めします。
int stockvalue = reader["StockValue"] != DbNull.Value ? Convert.ToInt32(reader["StockValue"]) : 0;
これが一つの方法です。
int stockvalue = Convert.IsDbNull(reader["StockValue"]) ? 0 : (int)reader["StockValue"];
TryParseを使用することもできます
int stockvalue = 0
Int32.TryParse(reader["StockValue"].ToString(), out stockvalue);
どの方法があなたに合っているか教えてください
DBクエリでこの変換を直接行うことができ、特別な場合を一緒に回避できます。
しかし、DBからNULLの代わりに「0」を返すことで情報を失うため、コードで一貫してそのフォームを使用できない限り、「クリーナー」とは呼びません。
使用 Nullable<int>
タイプ...int?
略して
私のプロジェクトには次の2つの拡張メソッドがあります。
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;
}
使用方法は次のようになります。
string companyName = dataReader.GetValueSafe("CompanyName", (reader, ordinal) => reader.GetString(ordinal));
あんまり。メソッドにカプセル化できます:
public int getDBIntValue(object value, int defaultValue) {
if (!Convert.IsDBNull(value)) {
return (int)value;
}
else {
return defaultValue;
}
そして、次のように呼び出します:
stockVaue = getDBIntVaue(reader["StockValue"], 0);
または、クエリでcoalesce
を使用して、戻り値を強制的にnull以外にすることもできます。
編集-受信したコメントに基づいてダムコードエラーを修正しました。
int? stockValue = reader["StockValue"] == null || reader["StockValue"] == DBNull.Value ? null : (int?)reader["StockValue"];