How do you properly check an SQLiteDataReader for null values? - c#

I am trying to read some rows from a table in an SQLite database. I have a try/catch around my reader code:
try {
using (SQLiteConnection dbCon = new SQLiteConnection("Data Source=" + dbPath)) {
dbCon.Open();
using (SQLiteCommand command = new SQLiteCommand(sqlcmd, dbCon)) {
using (SQLiteDataReader rdr = command.ExecuteReader()) {
while (rdr.Read()) {
}
catch(exception ex) { throw ex; }
Something like that.
My problem is that any way that I check the reader values, say like:
if (rdr[3].ToString() != "" && rdr[3] != null) {}
It will always pass that if and then still throw an exception of "The given key was not present in the dictionary."
I simply want to reliably check these values so that I can skip over one but without having to hit the catch every time.
Given the previous example of checking for null:
if (rdr[3].ToString() != "" || rdr[3] != null) {
int something = Convert.ToInt32(rdr[3]);
}
this will error everytime there is no value in that field, because it will also always pass the 2 checks in the if.

I once tried to check against the null-type, too. Actually, you have to check against the special type of DBNull:
if (rdr[3].GetType() != typeof(DBNull)) { }

Since the data reader returns the singleton instance DBNull.Value a null column's value will be of the type DBNull. We can leverage this fact by using the as operator to convert our value to a reference null if the column value is null
String varcharValue = rdr[3] as String;
So here we would either have an instance of string or a null reference if the column value is null.
Unfortunately, this technique will not work directly with value types. The following code will generate a compilation error:
int numberVlaue = rdr[1] as int; // Will not compile
However, we can use the nullible version of the type to accomplish a similar conversion:
int? nullibleNumberValue = rdr[1] as int?;
and the later check the HasValue property to see if the type is null.

Related

Converting null literal or possible null warning on DataRow in foreach

Updated my .NET Core 3.1 console application to use Nullables feature and have the following foreach loop.
DataTable profiles = DB.ListProfiles();
// CS8600 warning here
// v
foreach (DataRow r in profiles.Rows)
{
// processing code here
}
static public DataTable ListProfiles()
{
DataTable t = new DataTable();
using (SqlConnection conn = new SqlConnection(connString))
{
conn.Open();
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT * FROM [Table]";
using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
sda.Fill(t);
}
}
return t;
}
In this example, r has the compiler warning.
Converting null literal or possible null value to non-nullable type.
I am aware of the need to check for nulls and such. My question is has anyone figured out how with this new feature to get the compiler to realize that neither profiles nor profiles.Rows will ever be null? The t variable in ListProfiles could absolutely return no results, but that wouldn't make Rows null, would it?
If I use the null-coalescing operator ?? like this: profiles.Rows ?? ... and the warning would go away but I haven't been able to figure out what can go after it to actually work.
I have also tried using the ! operator from How to suppress Possible Null Reference warnings but that has no effect. The warning remains. While this works for other types, it doesn't seem to work for DataRowCollection.
I have tried various placements of null checks but only an explicit in-code suppression seems to have any effect.
The nullable value is r, not profiles or profiles.Rows, as correctly identified by the compiler. Just declare it as nullable, then handle the null check in the loop:
foreach (DataRow? r in profiles.Rows)
{
if(r == null)
continue;
// ...
}
The reason is that DataRowCollection (which is the type of the Rows property on the data table) is a non generic enumerable. That's what you get for using .NET 1.0 APIs.
The compiler considers the items of non generic enumerables to be of type object?, not object (or more accurately, IEnumerator.Current is an object?), because any such item in the collection could be null, and there are no generics to restrict the items to non nullable values.
Since specifying the type of a foreach variable simply inserts a cast for you, the end result is you need to declare the variable itself as nullable, since you can't safely cast a nullable value to a non nullable one.

how to handle null exception in C#

im getting null exception . while im directly exceciting this page. i want to handle null exception
C#
string json = "";
if (Request.QueryString["data"] !="")
{
json = Request.QueryString["data"];
var req = JsonConvert.DeserializeObject<Request>(json);//getting error in this line
string requestid = req.requestId;
SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MYSTRING"].ConnectionString);
SqlCommand cmd = new SqlCommand();
connection.Open();
}
error
Value cannot be null.
Parameter name: value
Well presumably Request.QueryString["data"] is null. You're currently checking whether it's a reference to an empty string, but not whether it's a null reference. I suspect you want to use string.IsNullOrEmpty to check that:
string json = Request.QueryString["data"];
if (!string.IsNullOrEmpty(json))
{
var req = JsonConvert.DeserializeObject<Request>(json);
...
}
You can follow following two approach:-
Approach 1:
if (Request.QueryString["data"] != null && Request.QueryString["data"].toString() != string.Empty)
{
.. Your Content Goes Here
}
Approach 2:
if (!string.IsNullOrEmpty(Request.QueryString["data"].toString()))
{
.. Your Content Goes Here
}
you can u string.isNullOrwhiteSpace() Method and it returns a bool ...true if the input is empty ...false if there is any characters
You are getting such error when Request.QueryString["data"] is null. so you should check for null before using this value. in c# null cannot directly converted to String. Better method is suggested by john skeet.
string json=Request.QueryString["data"];
if(string.IsNullOrEmpty(json)){//Do your code;}

Im having an error Object cannot be cast from DBNull to other types

I have an error on return Convert.ToInt32(dataGridView1[0, Row].Value); it says that 'Object cannot be cast from DBNull to other types.' My database field on student ID is int. Here is my code:
public int GetStudentID()
{
// The Student ID is the first cell of the current row
int Row = dataGridView1.CurrentRow.Index;
return Convert.ToInt32(dataGridView1[0, Row].Value);
}
public string GetISBN()
{
// The ISBN is the second cell of the current row
int Row = dataGridView1.CurrentRow.Index;
return dataGridView1[1, Row].Value.ToString();
}
There a two possible problems here:
You are getting nulls from the database but always expecting a value
You are getting nulls from the database but not handling them
For problem 1, ensure the query that you're executing cannot allow null values. Maybe you're missing a filter...?
For problem 2, you need to check for null values:
public int GetStudentID()
{
int Row = dataGridView1.CurrentRow.Index;
var val = dataGridView1[0, Row].Value;
if (object.Equals(val, DBNull.Value))
{
/* either throw a more appropriate exception or return a default value */
// let's assume a default value is fine
return -1;
}
return Convert.ToInt32(val);
}
Your dataGridView1[0, Row].Value must be NULL
Check for NULL or use a try-catch block with NullReferenceException like below
try
{
return Convert.ToInt32(dataGridView1[0, Row].Value);
}
catch(NullReferenceException e)
{
return 0;//No such student ID when NULL is encountered.
}
You should check for DBNull.Value. It is not the same as null.
if(DBNull.Value != dataGridView1[0, Row].Value)
{
// do convertion, etc
}
else
{
// handle null case
}
It's handy to have a method to manage this little detail, e.g.:
email = Database.GetValueOrNull<string>(sqlCommand.Parameters["#Email"].Value);
Implemented like this:
public static T GetValueOrNull<T>(Object column)
{
// Convert DBNull values to null values for nullable value types, e.g. int? , and strings.
// NB: The default value for non-nullable value types is usually some form of zero.
// The default value for string is null .
// Sadly, there does not appear to be a suitable constraint ("where" clause) that will allow compile-time validation of the specified type <T>.
Debug.Assert(Nullable.GetUnderlyingType(typeof(T)) != null || typeof(T) == typeof(string), "Nullable or string types should be used.");
if (!column.Equals(DBNull.Value)) // Don't trust == when the compiler cannot tell if type <T> is a class.
return (T)column;
return default(T); // The default value for a type may be null . It depends on the type.
}
Moving data from a variable to a database parameter with null conversion may be accomplished thusly:
sqlCommand.Parameters.AddWithValue("#Serial", serial ?? (object)DBNull.Value);

converting object to string has error [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 1 year ago.
My code is this :
SqlConnection scn = new SqlConnection(ClsPublic.GetConnectionString());
SqlCommand scm = new SqlCommand("SELECT Name FROM Table WHERE (Blogger = #Blogger)", scn);
scm.Parameters.AddWithValue("#Blogger", lblBloger.Text);
scn.Open();
MyLabel.Text = scm.ExecuteScalar().ToString();
scn.Close();
in this line :
lblLastNo.Text = scm.ExecuteScalar().ToString();
Has this error :
Object reference not set to an instance of an object.
or when I using if statement , shows same error
object Blogger= "";
if (Blogger.ToString() != string.Empty)
{
....
}
in below code again shows same error .
Most likely scm.ExecuteScalar() is bringing you a null value. You need to test the value returned before using it:
var result = scm.ExecuteScalar();
MyLabel.Text = result == null ? '' : result.ToString();
scm.ExecuteScalar() is returning null, or scm is null, or lblLastNo is null. That's the only reason you get the error 'Object reference not set ..'.
ExecuteScalar return an Object type. This is why you have the same behavior on scm.ExecuteScalar().ToString(); or Blogger.ToString().
The object type default implementation of the ToString method returns the fully qualified name of the type of the Object, as the following example shows.
If this object is NULL, you will receive the error Object reference not set to an instance of an object.
Your second case with :
object blogger= "";
if (blogger.ToString() != string.Empty)
{
....
}
Should not throw an Exception but return a string that represents the object instance. For example : "YourNameSpace.Blogger"
Please enclose with try catch block, so that you can handle runtime exceptions and its makes life easier to understand the problem. and for if (Blogger.ToString() != string.Empty) this u can check for Null condition or if its string. Then you can check for String.IsNullorEmpty
string str=blogger.toString();
if (String.IsNullOrEmpty(str))
//do something
else
//do other part
String Is Null or EMpty

FormatException: Input string was not in the correct format

I have Views field from one of my tables in the database. At first i allowed it to take nulls, and now it disallowed it to take null. The problem is that that exception is being thrown when i convert the SqlReader instance to an int..here is the code:
try
{
conn.Open();
SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
if (dr != null && dr.Read() && dr["Views"] != null && dr["PageNumber"] != null && dr["Replies"]!=null)
{
Name = dr["Name"].ToString();
ThreadName = dr["ThreadTitle"].ToString();
Views = int.Parse(dr["Views"].ToString());//it is being thrown here when i try to convert it to an int..How can i prevent that mistake from being thrown?
Replies = int.Parse(dr["Replies"].ToString());
Topic = dr["Theme"].ToString();
Subtopic = dr["Topics"].ToString();
PageNumber = int.Parse(dr["PageNumber"].ToString());
Time = (DateTime)dr["Time"];
}
dr.Close();
}
Try
View = dr["Views"] as int? ?? 0;
If the value in the db is null then above it's being cast into a nullable int which can accept nulls.
Use the coalesce operator ?? to set the value of View to some other value (in this case 0) if the value in the database IS null.
You can use int.TryParse() to avoid the error. If the probem is just the null, I would recommend to use System.Convert to handle these situations, because it's safer and clear:
View = System.Convert.ToInt32(dr["Views"]);
To avoid exception while convertion, use Int32.TryParse always.
How about
if(dr["Views"] != DBNull)
{
// do your parse here
}

Categories

Resources