Handling null values in C# - uploaded excel data sheet to database - c#

I'm trying to read in items from a spread sheet into a data table, which can then be uploaded to a database.
The column I'm having issues with has to read in values that are boolean values. However, sometimes the field is empty. Instead of 0's and 1's, I need to store null into this boolean value when the field is empty.
Here is the original line of code:
bool bool2 = Convert.ToBoolean(row["Bool_02"]);
This works well when the field isn't empty.
But I can't check if the field is empty first because you can't store null as a boolean value.
I tried making it a nullable value like so:
bool? bool2 = Convert.ToBoolean(row["Bool_02"]);
if(bool2 != true || false)
{
bool2 = null;
}
But I get an error - object cannot be cast from DBNull to other types.
I have to take the input of the column, check if its empty - if its empty then save null in the bool variable.
How can I do this?

But I can't check if the field is empty first because you can't store null as a boolean value.
Sure you can, just check if the field is DBNull before trying to convert it.
if(row["Bool_02"] is DBNull) return;
bool bool2 = Convert.ToBoolean(row["Bool_02"]);
If you'd like to stuff it in a nullable boolean, you need a ternary.
bool? bool2 = row["Bool_02"] is DBNull ? null : Convert.ToBoolean(row["Bool_02"]);
Untested, you might need a typecast to (bool?) in that ternary for it to compile.

Related

How to read null for null-able Boolean values

I am trying to read nullable values from a database. Right now my code is converting null values to false. How can I modify my code to allow for null values?
Ap1ExamTaken = dr["AP1_ExamTaken"] != DBNull.Value && Convert.ToBoolean(dr["AP1_ExamTaken"]),
I would like values that are null to be shown as null and not false.
You could use the conditional operator here, to set it to null if the value is DBNull.Value, or a non-nullable value otherwise:
Ap1ExamTaken = dr["AP1_ExamTaken"] == DBNull.Value ? null : (bool?) dr["AP1_ExamTaken"];
Note that this will throw an exception if dr["AP1_ExamTaken"] is a non-boolean, non-DBNull type, which I suspect is what you want.
You could write it more compactly as:
Ap1ExamTaken = dr["AP1_ExamTaken"] as bool?
... but then you'll end up with a null value if the value is some other type (a string, an integer etc) which I'd generally be alarmed about. (If my data doesn't have the shape I expect, I want to know ASAP.)

how to prevent exception null value from retrieving records using Oledb

while(r.Read())
{
ListViewItem item = new ListViewItem(r.GetString(2));
item.SubItems.Add(r.GetString(3));
item.SubItems.Add(r.GetString(4));
item.SubItems.Add(r.GetString(5));
item.SubItems.Add(r.GetString(6));
item.SubItems.Add(r.GetString(7));
item.SubItems.Add(r.GetString(8));
item.SubItems.Add(r.GetString(11));
lsvListOfBooks.Items.Add(item);
}
this code fills a listview with records.
but if the cell from the database is null,
it throws exception
Specified cast is not valid
and exits the thread and the rest of the records won't be displayed.
how can I handle it?
The problem is that null values in result columns are represented by a different type - DBNull to be precise - and it cannot be trivially cast to a string.
The simplest solution to this is to create an extension for the IDataReader interface that will detect DBNull values and convert them. Add this class to your code:
public static partial class Extensions
{
public static string GetNullableString(this IDataReader self, int ordinal)
{
return self.IsDBNull(ordinal) ? null : self.GetString(ordinal);
}
}
Now you can replace GetString with GetNullableString in your code and it should function as expected. The IsDBNull call will detect the null condition and return null instead of throwing an error.
Unfortunately this sort of thing is required for all of the data types. If a null value is valid for the field the IDataReader will use DBNull values that are incompatible with any of the nullable types.

IsNull() extention for checking null value for any object

I am adding new extension method for checking null value for any object on following criteria:
Should return true if value for class object is null
Should return true if object is of type string and having value null or Empty
Should return true if object is of type DateTime and having Min value.
Any other condition for null need to check.(Please suggest if required.)
Here is IsNull() extention method:
public static bool IsNull(this object obj)
{
if (obj == null || obj == DBNull.Value)
return true;
if (obj.GetType() == typeof(string))
return string.IsNullOrEmpty(obj.ToString());
if (obj.GetType() == typeof(DateTime))
{
DateTime _dateValue = DateTime.MinValue;
if (DateTime.TryParse(obj.ToString(), out _dateValue) && _dateValue == DateTime.MinValue)
return true;
}
return false;
}
Now my question is:
Do I need to add check differently for Value and Reference type
object?
Does this extension method handle all type of null check for any
object?
Any suggestion or improvement need to add in extension?
Do I need to add check differenty for Value and Reference type object?
Value types can not be null.
Does this externtion method handle all type of null check for any object?
It looks like (except value types)
Any suggestion or improvement need to add in extention?
As I said value types cannot be null, so you can add an extra condition to check whether the type is value type or not,if so you can return false
if(obj.GetType().IsValueType) return false;
By the way if you write this before the DateTime check,your DateTime condition will become unreachable.It doesn't make sense anyway but it's your choice.If you want to return true when the value equals to DateTime.MinValue it's completely up to you.
A few observations:
1) A value type will never be null. When called on a value type.. it will be boxed to an object.. and won't be null (unless you wrap it in a Nullable<T>).
2) Your method no longer checks for null.. it also checks for a minimum value and empty strings. An empty string is not null - its an empty value. A minimum value is not null.. its a value. It has too much responsibility here and should be renamed.
3) Given what I've said above.. you could just simply do this instead of writing your own function:
if (variable == default(variable.GetType()))
Since that checks for the default of all types.. value types such as DateTime, int, and classes for null. Then, your only other specific check is for DBNull.Value.

Specified cast is not valid.(integer value in datatable)

I want to check the following field in the datatable against null :
r.Field<int>("prod_type")
if (r.Field<int>("prod_type") != null &&
!string.IsNullOrEmpty(r.Field<int>("prod_type").ToString()))
but I get the following exception :
Specified cast is not valid.
How to check the integer value in the datatable against null or empty ?
The Field extension method supports nullable types. Use HasValue to check if a nullable is not null:
if (r.Field<int?>("prod_type").HasValue)
The error you are getting is indicating that the field in the datatable is not of type int. If it is of type int it can't hold null value, instead you can try int? which is Nullable.
r.Field<int?>("prod_type") != null
If prod_type is indeed an int field in the database, try doing it like this:
if (r.Field<int?>("prod_type") != null)

Why can't I use '??' operand for System.DBNull value?

I have an Oracle data table fetching columns that be null. So I figure to keep the code nice and simple that I'd use the ?? operand. AlternatePhoneNumber is a string in my C# model.
AlternatePhoneNumber = customer.AlternatePhoneNumber ?? ""
However, even with that code I still get the error.
System.InvalidCastException: Unable to cast object of type 'System.DBNull' to type 'System.String'.
I know what the error means but why is ?? not usable on DBNull? Isn't null and DBNull essentially the same?
Thank you.
The ?? operator only applies to actual nulls.
null and DBNull.Value are not the same; DBNull.Value is simply a placeholder object.
Also, that exception is coming from inside the AlternatePhoneNumber property, before your ?? operator executes. (Your code doesn't have a cast).
If customer is a row in a typed dataset, change the column's NullValue property in the designer.
null and DBNull are not the same. System.DBNull is an actual object.
The problem is that AlternatePhoneNumber is a string. DBNull is not.
Try this instead:
AlternatePhoneNumber = (customer.AlternatePhoneNumber as string) ?? ""
Do this:
public T IfNull<T>(object o, T value)
{
return (o == DbNull.Value) ? value : (T)o;
}
DBNull is a type with a single value, and is not the same as a null string reference, which is why you can't use ??. You could do this however:
string alternativePhoneNumber = DBNull.Value.Equals(customer) ? string.Empty : ((Customer)customer).AlternatePhoneNumber;
As other replies state, null means a reference that refers to no object, while DBNull is a class supplied by ADO.NET to indicate when a field or value is NULL at the database (or in a DataTable).
While you can use the conditional (ternary) operator (?:) to do what you want:
AlternatePhoneNumber = customer.AlternatePhoneNumber is DBNull
? ""
: customer.AlternatePhoneNumber;
I tend to wrap this up in an extension method:
static class NullExtensions
{
public static T WhenNull<T>( this object value, T whenNullValue )
{
return (value == null || value is DBNull)
? whenNullValue
: (T)value;
}
}
which I find makes the code easier to read and understand.
AlternatePhoneNumber = customer.AlternatePhoneNumber.WhenNull( "" );
DBNull is NOT a real "null".
The "??" - operator detects only null - references, not objects that emulate "null" behavior.

Categories