String.IsNullOrEmpty VS IsDBNull in validation when using IIF and IF ELSE - sql

This is not clear to me, so if anyone can explain in detailed if what is the difference of the two functions (IsDBNull and String.IsNullOrEmpty) of VB.Net.
Below is my scenario why i ask that, i have column Company in my table which the value is NULL, then i used IIF function of vb.net to validate if it is NULL then assign empty string (""), else assign the value coming from data table
Scenario:
Below is using String.IsNullOrEmpty and i get a conversion error:
Conversion from type 'DBNULL' to 'String' is not valid.
txtCompany.Text = IIf(String.IsNullOrEmpty(dtSample.Rows(grdInfo.SelectedIndex).Item("Company")).ToString, "", dtSample.Rows(grdInfo.SelectedIndex).Item("Company"))
However when i replace String.IsNullOrEmpty by IsDBNull , the validation works fine.
txtCompany.Text = IIf(IsDBNull(dtSample.Rows(grdInfo.SelectedIndex).Item("Company")).ToString, "", dtSample.Rows(grdInfo.SelectedIndex).Item("Company"))
EDIT:
And it is confusing because if i did the validation using IF ELSE condition (see sample code below) with the use of String.IsNullOrEmpty, it works fine.
If String.IsNullOrEmpty(dtSample.Rows(grdInfo.SelectedIndex).Item("Company").ToString) = True Then
txtCompany.Text = ""
Else
txtCompany.Text = dtSample.Rows(grdInfo.SelectedIndex).Item("Company").ToString
End If
The confusing part is when i used IIF(String.IsNullOrEmpty...etc) it returns an error. but when i used the normal IF String.IsNullOrEmpty(dtSample.Rows....etc) = True it works fine.
Any explanation would much appreciated. Thanks

TL;DR
String.IsNullOrEmpty() checks only for Empty ([blank] i.e. '' or "") or Null values it does not check DBNull, if any field coming from database has its value DBNull it will raise an error.
IsDBNull() checks for DBNull (it is not same as Null)
.ToString will convert DBNull to Empty String i.e. ''
Details
Consider following SQL table example (using SQL Server as base)
Table Structure:
Column_Name Type and Size Other Properties
---------------- ------------- ----------------------
Company_ID int IDENTITY(1,1) NOT NULL
Company_Name nvarchar (50) NOT NULL
Company_Address nvarchar (50) NULL
INSERT statements:
INSERT [tbl_company] ([Company_Name], [Company_Address]) VALUES ('ABC', 'QWERT')
INSERT [tbl_company] ([Company_Name], [Company_Address]) VALUES ('ASD', ' ')
INSERT [tbl_company] ([Company_Name], [Company_Address]) VALUES ('XYZ', '')
INSERT [tbl_company] ([Company_Name]) VALUES ('PQR')
Table Data:
Company_ID Company_Name Company_Address
----------- ---------------- ---------------
1 ABC QWERT
2 ASD [SPACE]
3 XYZ [BLANK]
4 PQR NULL
Testing Company_Address with IsNullOrEmpty() and IsDBNull() using a SqlDataReader (r):
Company_ID IsNullOrEmpty(r("Company_Address")) IsDBNull(r("Company_Address"))
---------- ----------------------------------- ------------------------------
1 False False
2 False False
3 True False
4 ERROR True
And now specific to the Question
What the OP is trying here, lets consider all statements one by one
The IIF statement with IsNullOrEmpty (wrong)
txtCompany.Text = IIf(String.IsNullOrEmpty(dtSample.Rows(grdInfo.SelectedIndex).Item("Company")).ToString, "", dtSample.Rows(grdInfo.SelectedIndex).Item("Company"))
In this statement OP is accessing the value as dtSample.Rows(grdInfo.SelectedIndex).Item("Company") and checking it with IsNullOrEmpty() and then converting the result of IsNullOrEmpty to string using .ToString i.e. IsNullOrEmpty(value).ToString(). If the value is DBNull it will always return an error. The correct way to use it is
IsNullOrEmpty(dtSample.Rows(grdInfo.SelectedIndex).Item("Company").ToString)
See last part Company")).ToString vs Company").ToString), just a case of MISPLACED ")"
Second (IIF with IsDBNull) and third (IF with IsNullOrEmpty) statements of OP are correct
txtCompany.Text = IIf(IsDBNull(dtSample.Rows(grdInfo.SelectedIndex).Item("Company")).ToString, "", dtSample.Rows(grdInfo.SelectedIndex).Item("Company"))
If String.IsNullOrEmpty(dtSample.Rows(grdInfo.SelectedIndex).Item("Company").ToString) = True Then
txtCompany.Text = ""
Else
txtCompany.Text = dtSample.Rows(grdInfo.SelectedIndex).Item("Company").ToString
End If
As regards to the second statement OP is correctly ordering the parameters i.e. first Company field is converted to string using dtSample.Rows(grdInfo.SelectedIndex).Item("Company").ToString. This converts any DBNull to Empty string and then it checked for IsNullOrEmpty. Now as the value has already been converted to EmptyString it will not give any error.
Old discussions with OP
The difference is clear in your text. Your first statement is:
txtCompany.Text = IIf(String.IsNullOrEmpty(dtSample.Rows(grdInfo.SelectedIndex).Item("Company")).ToString, "", dtSpecifierRebate.Rows(grdInfo.SelectedIndex).Item("Company"))
and the second one is
If String.IsNullOrEmpty(dtSample.Rows(grdInfo.SelectedIndex).Item("Company").ToString) = True Then
Now break them apart, first statement (IIF)
String.IsNullOrEmpty(dtSample.Rows(grdInfo.SelectedIndex).Item("Company")).ToString
'Item("Company")).ToString
And second part (IF)
String.IsNullOrEmpty(dtSample.Rows(grdInfo.SelectedIndex).Item("Company").ToString)
'Item("Company").ToString)
Found any difference?
In first statement you are converting the result of IsNullOrEmpty to String
In second one you are converting .Item("Company") ToString and then comparing it.
If .Item("Company") returns DBNull
then IsNullOrEmpty failed because .Item("Company") returned type DBNull whereas IsNullOrEmpty checks for null
IsDBNull worked because it checks for DBNull
All point of a misplaced bracket ")" It's a typo
And regarding your usage of these statements:
If and IIF need to check the results as booleans and not as strings
It is better recommended to remove the ToString portion of your statements

You cannot mix and match String.IsNullOrEmpty and IsDBNull because they work on two different things. The first on strings, the second on Data items read from the database.
But a very important element of this is that your code is invalid. Neither "Scenario" snippet compiles under Option Strict. If you leave VB to guess what you mean, you will get confusing results.
Snippet 1:
txtCompany.Text = IIf(String.IsNullOrEmpty(dtSample.Rows(grdInfo.SelectedIndex).Item("Company")).ToString, "", dtSample.Rows(grdInfo.SelectedIndex).Item("Company"))
Simplified:
Dim foo = IIf(String.IsNullOrEmpty(zDT.Rows(23).Item("Name")).ToString,
"", zDT.Rows(23).Item("Name"))
This is illegal because zDT.Rows(23).Item("Name") is an object, but String.IsNullOrEmpty expects a string. Your ToString is misplaced - it is not converting the db Item, it is converting the entire IIF bool expresion!
The compiler warns you of both withOption Strict On.
The conversion throws an exception because VB must convert the db Object item ( zDT.Rows(23).Item("Name")) to a string. The way it does it results in an error when when the db data is DBNull.
Snippet 2:
txtCompany.Text = IIf(IsDBNull(dtSample.Rows(grdInfo.SelectedIndex).Item("Company")).ToString, "", dtSample.Rows(grdInfo.SelectedIndex).Item("Company"))
Simplified:
foo = IIf(IsDBNull(zDT.Rows(23).Item("Name")).ToString,
"", zDT.Rows(23).Item("Name"))
This is slightly better but a string is till being used in place of the Boolean expression. When fixed, you have:
IsDBNull(zDT.Rows(23).Item("Name"))
IsDBNull is testing a database item (Object) to see if it has data. It will work. IsNullOrEmpty should not be used to test for DBNull and cant with Option Strict. You'd have to convert the dbItem to string first, then it will only work depending on how you convert.
' cant use string method to test an object
String.IsNullOrEmpty(zDT.Rows(23).Item("Name"))
' this will work:
String.IsNullOrEmpty(zDT.Rows(23).Item("Name").ToString)
' this will not:
String.IsNullOrEmpty(CStr(zDT.Rows(23).Item("Name")))
Use DBNull tests for data objects, and IsNullOrEmpty on strings.
Also, if you use the newer If operator in place of the old IIf function you can avoid other issues. The operator allows short circuiting, the syntax is the same:
Dim foo = If(bool expr, True result, False result)

IsDBNull Function :
Returns a Boolean value that indicates whether an expression evaluates to the System.DBNull class.
IsDBNull returns True if the data type of Expression evaluates to the DBNull type; otherwise, IsDBNull returns False.
The System.DBNull value indicates that the Object represents missing or nonexistent data. DBNull is not the same as Nothing, which indicates that a variable has not yet been initialized. DBNull is also not the same as a zero-length string (""), which is sometimes referred to as a null string.
example :
Dim testVar As Object
Dim nullCheck As Boolean
nullCheck = IsDBNull(testVar)
testVar = ""
nullCheck = IsDBNull(testVar)
testVar = System.DBNull.Value
nullCheck = IsDBNull(testVar)
' The first two calls to IsDBNull return False; the third returns True..
String.IsNullOrEmpty :
Indicates whether the specified string is null or an Empty string.
IsNullOrEmpty is a convenience method that enables you to simultaneously test whether a String is null or its value is Empty.
Example :
Class Sample
Public Shared Sub Main()
Dim s1 As String = "abcd"
Dim s2 As String = ""
Dim s3 As String = Nothing
Console.WriteLine("String s1 {0}.", Test(s1))
Console.WriteLine("String s2 {0}.", Test(s2))
Console.WriteLine("String s3 {0}.", Test(s3))
End Sub
Public Shared Function Test(s As String) As String
If String.IsNullOrEmpty(s) Then
Return "is null or empty"
Else
Return String.Format("(""{0}"") is neither null nor empty", s)
End If
End Function
End Class
'The example displays the following output:
'String s1 ("abcd") is neither null nor empty.
'String s2 is null or empty.
'String s3 is null or empty.

The IsNullOrEmpty function checks whether or not a string is empty or null. DBNull is not null (Nothing), but rather is a class that indicates a value from a database does not exist. IsDbNull checks for whether or not a value equals DBNull.
You may not be getting the error you mention in the question on the line of code referenced as this runs just fine for me:
strTest = IIf(String.IsNullOrEmpty(DBNull.Value.ToString), "", DBNull.Value)

Related

msaccess db field is zero length string but vba isnull() function returns null

NULLs again!!!!
I have set a field to zero length string if there is nothing and this applies to about half of the records.
Running the sql statement:
select * from contacts WHERE organisation is null
return no rows as expected.
But the VBA
Debug.Print Len(Me.Organisation)
If IsNull(Me.Organisation) Then
Label50.Caption = "null"
Else
Label50.Caption = Len(Me.Organisation)
End If
shows all the records with zero length organisation as null rather than 0
The field is defined on the db as short text with the following parameters:
Why is VBA telling me it is null when it is clearly not?
Programmatically changing property of a control affects ALL instances of control. Use a textbox with expression in ControlSource instead of VBA changing label.
=IIf(IsNull(Organisation), "Null", Len(Organization))
Setting a field to allow ZLS does not guarantee field contains ZLS when there is no data. I NEVER allow ZLS in fields.
Debug.Print Len(Me.Organisation)
If Me.Organisation.text=" " Then
Label50.Caption = "null"
Else
Label50.Caption = Len(Me.Organisation)
End If

Null Check a column value that can be Null without two DLookups?

How do I remove one DLookup from code similar to this example?
Dim sCustomerName as String
If IsNull(DLookup("sName", "tblCustomers", "iCustomerID=12345")) Then
MsgBox "Customer name is null!"
Else
sCustomerName = DLookup("sName", "tblCustomers", "iCustomerID=12345")
End If
In VBA, reading a column value that can be Null (or missing) into a variable, and then comparing it to Null gives an error. Is there a better way to do these checks?
Obviously, if there's no performance penalty, it's not bad code because of the performance hit. Is there?
Even if not, it has duplicated/copy-pasted code. How can it be rewritten to avoid this?
A Variant data type can store Null values. Try to get the value and check if Null.
Dim customerName As Variant
customerName = DLookup("sName", "tblCustomers", "iCustomerID=12345")
If Not IsNull(customerName) Then
'do stuff
End If
Another approach is the Nz() function:
You can use the Nz function to return zero, a zero-length string (" "), or another specified value when a Variant is Null.
Dim customerName As String
customerName = Nz(DLookup("sName", "tblCustomers", "iCustomerID=12345"), vbNullString)
If customerName <> vbNullString Then
'do stuff
End If

DBNull Exception from datatable row

I am a beginner and stuck at one place. So basically I need to set date value to one of the datarow. But when ever date is empty string I need to set it to "Now". But I am not able to do so.
I am getting exception as System.Data.StrongTypingException' "The value for column 'dteEntry' in table is DBNull
Here is what I have
Dim strTimeStamp as String = "" ' code taken out for brevity
' dteEntry is of Date datatype
Dim newRow As ABC.Dataset.dtCardRow = ret.NewdtCardRow()
If (Date.TryParse(strTimeStamp, newRow.dteEntry)) Then
else
newRow.dteEntry = Now
End If
This is a strongly typed DataSet which auto generates code like the NewdtCardRow method that you have used above. Every property that is nullable has also a method to check if it's null, it's name is derived from the name of the property, something like IsEntryDate_Null, which you can use to check if the value is NULL. Otherwise you get an exception if you read that property as you do in Date.TryParse.
But in this case you can prevent this exception by using a local variable for Date.Parse instead of passing the property itself:
newRow.dteEntry = DateTime.Now ' writing doesnt cause this exception
Dim entryDate As Date
If Date.TryParse(strTimeStamp, entryDate) Then
newRow.dteEntry = entryDate ' writing doesnt cause this exception
End If

Why is my DLookup producing "invalid use of null" Error: 94

In my Access VBA code, I have several DLOOKUP functions in a sequence. They are all the same except for the value the parameter they are returning from 'studys'.
The last one is occasionally producing the error:
invalid use of null
The line of code producing the error is:
necropsy = DLookup("[Necropsy]", "Studys", "[Primary Key] = " & ID)
The necropsy value in Study's is a null Date occasionally but that is why I am looking it up.
In comparison the line above it:
studyEnd = DLookup("[Study End]", "Studys", "[Primary Key] = " & ID)
This code runs fine. It would never return a null value as study end is never null.
What's up?
If you have Dim necropsy As Date, necropsy can not accept Null because Null is not a Date/Time value.
If you want to allow necropsy to accept Null, make it a Variant instead: Dim necropsy As Variant
A date cannot be Null in VBA.
If you simply remove the variable declaration it will be returned as a date when not null.

insert null into date column in database

I've got a gridview in vb.net and am trying to insert a null value into a database column - unfortunately, i keep seeing 1900-01-01 being inserted. below is my code and i need help.
Protected Sub gvPOItems_RowCommand(sender As Object, e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles gvPOItems.RowCommand
If (e.CommandName = "save") Then
For i As Integer = 0 To gvPOItems.Rows.Count - 1
Dim row As GridViewRow = gvPOItems.Rows(i)
Dim value3 As String = DirectCast(row.Cells(9).FindControl("txtbxExpireDate"), TextBox).Text.Replace("'", "''")
If String.IsNullOrEmpty(value3) Or value3.ToString() Is Nothing Then
value3 = DBNull.Value.ToString()
End If
Next
End Sub
It works when the value isn't null, because you're injecting the value in that string:
INSERT INTO table (datecolumn) VALUES ('2014-08-04')
However, DBNull.Value.ToString() resolves to an empty string. When you then try and insert said empty string into your database via a SQL-injection-prone approach, you're really running a query something like:
INSERT INTO table (datecolumn) VALUES ('')
And that puts in the default value of 1900-01-01. What you need is:
INSERT INTO table (datecolumn) VALUES (NULL)
You need to parameterize your queries. Then you can pass Nothing directly to your SQL command, and it will work. Aside from that, you have to shift some abstraction so that you only add ' characters if the argument is not Nothing, and if it is, then you need to pass the string NULL.
As for the code you do have, there are some bugs here, too.
Dim value3 As String = DirectCast(row.Cells(9).FindControl("txtbxExpireDate"), TextBox).Text.Replace("'", "''")
If String.IsNullOrEmpty(value3) Or value3.ToString() Is Nothing Then
value3 = DBNull.Value.ToString()
End If
value3 is a string, and as per documentation, string.ToString() returns an unconverted instance of the original value. In other words, String.IsNullOrEmpty(value3) already does what you're checking for in your latter condition, except if the latter condition were ever true it would throw a NullReferenceException (or whatever the equivalent of that is in VB, I don't know whether it uses Nothing because I've literally never written anything in VB before).
Next, you should be aware that value3 will never be Nothing. It comes directly from a TextBox.Text property, and will consequently be at most an empty string. That's fine, because you check for that in IsNullOrEmpty, but since you added on the Is Nothing I thought I'd better point that out.
So basically, long story short, parameterize your queries. For all our sakes. But if you absolutely aren't going to, this should fix this particular problem:
Dim value3 As String = DirectCast(row.Cells(9).FindControl("txtbxExpireDate"), TextBox).Text
If String.IsNullOrEmpty(value3)
value3 = "NULL"
Else
value3 = "'" + value3.Replace("'", "''") + "'"
End If
You'll then have to adjust your later code to not add in those quotes, itself.