web-dev-qa-db-ja.com

C#のDBNullおよびnull許容型-変換の最もクリーンな形式

いくつかの列があるDataTableがあります。これらの列の一部はNULL可能です。

_DataTable dt;  // Value set. 
DataRow dr;  // Value set. 

// dr["A"] is populated from T-SQL column defined as: int NULL 
_

次に、DataRowの値からnull可能な変数に変換する最もクリーンな形式は何ですか。

理想的には、私は次のようなことができるでしょう:

_int? a = dr["A"] as int?; 
_

Edit:これを実行できることがわかります。スキーマ型は整数ではないので、これは常にnullを返します。 Rubenによるdr.Field<int?>("A")の使用の答えは、型の不一致が暗黙のうちに失敗しないことを保証します。もちろん、これは完全な単体テストで取り上げられます。

代わりに、私は通常、次の行に沿って何かを入力しています:

_int? a = dr["A"] != DBNull.Value ? (int)dr["A"] : 0; 
_

これはかなり多くのキーストロークですが、さらに重要なことに、誰かが間違ったキーストロークで何かを詰め込む余地がより多くあります。はい、単体テストはこれを拾いますが、私はむしろそれを完全に止めたいです。

この状況で最もクリーンでエラーが発生しにくいパターンは何ですか。

37
user111013

LINQ in ActionのLINQ to DataSetsの章 は良い読み物です。

表示されるのはField<T>拡張メソッド。次のように使用されます:-

int? x = dr.Field<int?>( "Field" );

または

int y = dr.Field<int?>( "Field" ) ?? 0;

または

var z = dr.Field<int?>( "Field" );
55
Ruben Bartelink

これが.NET 3.5のDataRowExtensionsクラスの目的です。これは、DataRowと.NET型の間でnull可能(およびnull不可)データをラウンドトリップするための静的Field<T>およびSetField<T>メソッドを提供します。

int? fld = row.Field<int?>("ColumnA")

row["ColumnA"]DBNull.Valueが含まれている場合はfldnullに設定し、整数が含まれている場合はその値に設定し、それ以外に何かが含まれている場合は例外をスローします。そして帰る途中で

row.SetField("ColumnA", fld);

同じことを逆に行います。fldnullが含まれている場合、row["ColumnA"]DBNull.Valueに設定し、それ以外の場合はfldの値に設定します。

Fieldがサポートするすべての値の型(null不可の型を含む)にはSetFieldDataRowのオーバーロードがあるため、取得と設定に同じメカニズムを使用できますデータ型に関係なくフィールド。

12
Robert Rossney
int? a = (int?)dr["A"]
4
bniwredyc

以下は安全に機能します:

スニップ:

public static class SqlDataReaderEx
{
    public static int TryParse(SqlDataReader drReader, string strColumn, int nDefault)
    {
        int nOrdinal = drReader.GetOrdinal(strColumn);
        if (!drReader.IsDbNull(nOrdinal))
            return drReader.GetInt32(nOrdinal);
        else
            return nDefault;
    }
}

使用法:

SqlDataReaderEx.TryParse(drReader, "MyColumnName", -1);
1
KMån

なぜLINQを使わないのですか?それはあなたのために変換を行います。

1
stepanian

拡張メソッド!

次のようなもの:

public static class DataRowExtensions
{
    public static Nullable<T> GetNullableValue<T>(this DataRow row, string columnName)
        where T : struct
    {
        object value = row[columnName];
        if (Convert.IsDBNull(value))
            return null;

        return (Nullable<T>)value;
    }

    public static T GetValue<T>(this DataRow row, string columnName)
        where T : class
    {
        object value = row[columnName];
        if (Convert.IsDBNull(value))
            return null;

        return (T)value;
    }
}

次のように使用します。

int? a = dr.GetNullableValue<int>("A");

または

string b = dr.GetValue<string>("B");
0
Brannon