Pregunta

I'm looking at some code for a .net program I'm working on. The previous author of the program gave the code to me over a year ago. Suddenly, I am seeing an exception thrown from code that I haven't touched:

if ((string)row["LevelName"] != "ABC")

The exception is "Unable to cast object of type 'System.DBNull' to type 'System.String'.

I thought that string was a nullable data type, so how can I possibly be getting this exception?

¿Fue útil?

Solución

DBNull is it's own class, which contains a singleton instance of itsself in a property called Value. DBNull.Value is not equal to null, as it is a reference to an instance of this class.

Most, if not all database wrappers will return DBNull.Value instead of null when there is no value. One of the reasons for this is because returning a real null could mean there is no row at all, not just a null value in the column (it depends on what objects you're using to get the values though).

Generally, the as operator is very usefull with DBNull and can be used with any nullable type (including string).

string str = reader["Name"] as string;
int? i = reader["Age"] as int?;

It might also be worth mentioning that the ?? operator is very usefull here too, when you need a non-nullable value type (although it doesn't look too pretty).

int i = reader["Age"] as int? ?? -1;

I find this very handy as a little just-in-case scenario in a LINQ select clause.

Otros consejos

I believe what you're looking for is:

if ((row["LevelName"] as String) != "ABC")

There is no implicit cast between DBNull and String.

It may have worked before because there just happened to be no NULLs in that column in your database. Maybe some data got corrupt, or someone changed a NOT NULL constraint on the table.

Basically if you explicitly cast something, you better make sure they have compatible dynamic types otherwise an exception is thrown. The as operator basically says "cast it to this if possible, otherwise the logical value is null." Obviously, the as operator only works on reference types since structs cannot be null.

DBNull means there is no data in the given database column. This can occur if a new record is created in the database but no value is assigned to the "LevelName" column.

DBNull is not the same as a null object reference or null string variable. DBNull means the column data has never been set. If you assign a null to the "LevelName" column, then the column has been initialized and it will return null (not DBNull).

DBNull represents a null value in the database. This is not the same as a .NET null, which indicates an empty reference.

The code suddenly fails because someone changed or inserted a record that has nulls in it.

Yes, string is nullable, but you cast a dbnull to string. You must check for dbnull, and replace it with null if it's there.

There is a difference between the .NET null and the DBNull.Value. Here you can see what the DBNull class is and the Value field of that class.

You should be able to do something like this:

if (row["LevelName"].Value == DBNull.Value)
    return false;
else if (row["LevelName"].ToString() != "ABC")
    // do something
    // ....
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top