2

null許容のDateTimeフィールド「BirthDate」があります。既存のコードはこれをこのように処理していました。

info.BirthDate = (DateTime?)reader["Birthdate"];

これにより「無効なキャスト」エラーが発生し、破損します。わかりました。これは、nullがsqlとは異なる方法で返され、「DBNull」タイプであるためです。

これに対する修正は次のようになりました

if (reader["Birthdate"] != DBNull.Value)
{
    info.Birthdate = (DateTime)reader["Birthdate"];
}

なぜこれが正確に機能するのか誰かが説明できますか?..私はDBNullの.Value部分で特に迷っています。DBNullとして返される場合、コードはこのブロック内にどのように到達しますか?

4

2 に答える 2

5

DBNullシングルトンです。その例は 1 つしかありません。でこのインスタンスにアクセスしますDBNull.ValueDBNull(.Value)比較は、が返されたかどうかをチェックし、返されなかった場合 ( !=)、安全に にキャストできることを認識しますDateTime

MSDNから:

DBNull はシングルトン クラスです。つまり、このクラスのこのインスタンスのみが存在できます。

Convert.IsDBNullまたは、次の方法を使用することもできます。

if (!Convert.IsDBNull(reader["Birthdate"]))
{
    info.Birthdate = (DateTime)reader["Birthdate"];
}
于 2013-03-14T15:52:29.720 に答える
0

DBNullではなくです。@aKzenT が説明したように、シングルトンとして実装されます。つまり、そのタイプのインスタンスは1 つしか存在できません。その 1 つの値を取得する方法は、静的プロパティを使用することです。.Value

DBNullこれにより、どのインスタンスも値と別のインスタンスへの参照の両方が等しいため、比較が容易になりDBNullます。

より意味のあるチェックを行う別の方法は次のとおりです。

int columnIndex = reader.GetOrdinal("Birthdate");
if (!reader.IsDbNull(columnIndex)) // IsDbNull should have a string overload, but it does not.
{
    info.Birthdate = (DateTime)reader["Birthdate"];
}
于 2013-03-14T16:02:33.030 に答える