これを行うためのより良い/よりクリーンな方法はありますか?
int stockvalue = 0;
if (!Convert.IsDBNull(reader["StockValue"]))
stockvalue = (int)reader["StockValue"];
これを行うためのより良い/よりクリーンな方法はありますか?
int stockvalue = 0;
if (!Convert.IsDBNull(reader["StockValue"]))
stockvalue = (int)reader["StockValue"];
The shortest (IMHO) is:
int stockvalue = (reader["StockValue"] as int?) ?? 0;
Explanation:
私がこれを処理する方法は
int? stockvalue = reader["StockValue"] as int?;
とてもシンプルですっきりとした一行。何らかの理由で 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 列を許可しないようにしています。それを処理するためのコーディングにはより多くのオーバーヘッドがあり、問題を再考するだけで必要なくなる場合があります。
を参照すると便利ですがreader["StockValue"]
、あまり効率的ではありません。また、 type を返すため、厳密に型指定されていませんobject
。
代わりに、コード内で次のようにします。
int stockValueOrdinal = reader.GetOrdinal("StockValue");
int? stockValue = reader.IsDbNull(stockValueOrdinal) ?
null :
reader.GetInt32(stockValueOrdinal);
もちろん、すべての序数を一度に取得してから、コード全体で使用することをお勧めします。
はい、使用できますint?
。この方法では、デフォルト値を 0 ではなく null にすることができます。stockvalue の結果が 0 になる可能性があるため、データベースが 0 か null かについて混乱することはありません。たとえば、このように (pre nullable)、値が割り当てられていないことを表す -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.
}
int stockvalue = reader["StockValue"] != DbNull.Value ? Convert.ToInt32(reader["StockValue"]) : 0;
これが1つの方法です。
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」を返すと情報が失われるため、コードでそのフォームを一貫して使用できない限り、それを「よりクリーン」とは呼びません。
あまり。メソッドにカプセル化できます。
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"];
タイプを使用して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));