简体   繁体   中英

Explain handling DBNull?

I have a nullable DateTime field "BirthDate" the existing code was handeling this in such a way

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

This causes an "Invalid Cast" error and it breaks. Ok, I understand this is because nulls are returned differently from sql and are of the type "DBNull"

Fix for this turned out to be

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

Can someone explain why exactly this works?..I'm particularly lost on the .Value part of DBNull. If it IS returning as DBNull how does the code even reach inside this block?

DBNull is a singleton. There is only one instance of it. You access this instance with DBNull.Value . The comparison checks if DBNull(.Value) is returned and if it is not returned ( != ) then it knows it can safely cast it to a DateTime .

From MSDN :

DBNull is a singleton class, which means only this instance of this class can exist.

Alternatively you could use the Convert.IsDBNull method:

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

DBNull is a type , not a value . As @aKzenT explained, it is implemented as a singleton, meaning there can only only be one instance of that type. The way to get to that one value is through the static .Value property.

This makes it easy to do comparisons since any DBNull instance is equal in both value and reference to another DBNull instance.

Another way to do that check which may make more sense is:

int columnIndex = reader.GetOrdinal("Birthdate");
if (!reader.IsDbNull(columnIndex)) // IsDbNull should have a string overload, but it does not.
{
    info.Birthdate = (DateTime)reader["Birthdate"];
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM