The problem is that DBNull.Value is not null. It seems that you want to replace DBNull.Value with 0.0m, but a better solution would be to use nullable types. That is, use decimal?
rather than decimal
. Then you can use the as
operator:
decimal? unitPrice = row["UnitPrice"] as decimal?;
If you can't do that, you can do this instead:
decimal unitPrice = (row["UnitPrice"] as decimal?) ?? 0.0m
or
decimal unitPrice = (row["UnitPrice"] as decimal?).GetValueOrDefault();
A helper function would make it slightly less verbose, if you do this a lot:
T FromObject<T>(object o) where T : struct { return (o as T?).GetValueOrDefault(); }
then
decimal unitPrice = FromObject<decimal>(row["UnitPrice"]);
If you need a non-zero default value:
T FromObject<T>(object o, T defaultValue) where T : struct
{
return (o as T?).GetValueOrDefault(defaultValue);
}
then
decimal unitPrice = FromObject<decimal>(row["UnitPrice"], Decimal.MinValue);
The drawback to this approach is that if you change the underlying type of the database column, you will start getting spurious zeros back instead of exceptions. That's because if the object is, for example, 1.2f
, then o as decimal?
will return null, which will then be replaced by 0.0m. The expression o == DBNull.Value ? 0.0m : (decimal)o
, however, will be equivalent to (decimal)(object)1.2f
, which will fail with an InvalidCastException, which is better than giving all of your products away for free.