web-dev-qa-db-ja.com

C#でDBNullを処理する

これを行うためのより良い/きれいな方法はありますか?

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

最短(IMHO)は次のとおりです。

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

説明:

  • reader ["StockValue"]タイプがintの場合、値が返され、「??」演算子は結果を返します
  • reader ["StockValue"]がタイプint(DBNullなど)ではない場合、nullが返され、「??」演算子は値0(ゼロ)を返します。
59

私がこれを扱う方法は

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

非常にシンプルでクリーンな1行。何らかの理由で絶対にnull値を持つことができない場合(値に意味があるかどうか、またはプリミティブ型に対してユニット化されているかどうかを知りたいので、通常は不十分な推論を見つけます):

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

数日前に拡張メソッドを書きました。それを使用することで、あなたはただすることができます:

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);
    }
}
11
Vivek
int? stockvalue = (int?)(!Convert.IsDBNull(result) ? result : null);

DBNullがコードに引き継がれるようにするための1つの可能な解決策。私たちのグループでは、ベストプラクティスとして、本当に必要でない限り、データベースでNULL列を許可しないようにします。それを処理するためのコーディングにはより多くのオーバーヘッドがあり、場合によっては問題を再考するだけで不要になることがあります。

10
Digicoder

はい、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.
}
7
kemiller2002

reader["StockValue"]を参照するのは便利ですが、あまり効率的ではありません。型objectを返すため、厳密に型指定されていません。

代わりに、コード内で次のようなことを行います。

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

もちろん、すべての序数を一度に取得し、コード全体で使用することをお勧めします。

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

これが一つの方法です。

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

TryParseを使用することもできます

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

どの方法があなたに合っているか教えてください

1
sidney.andrews

DBクエリでこの変換を直接行うことができ、特別な場合を一緒に回避できます。

しかし、DBからNULLの代わりに「0」を返すことで情報を失うため、コードで一貫してそのフォームを使用できない限り、「クリーナー」とは呼びません。

1
lexu

使用 Nullable<int>タイプ...int?略して

0
Rich

私のプロジェクトには次の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));
0
Andrew Bezzub

あんまり。メソッドにカプセル化できます:

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

そして、次のように呼び出します:

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

または、クエリでcoalesceを使用して、戻り値を強制的にnull以外にすることもできます。

編集-受信したコメントに基づいてダムコードエラーを修正しました。

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