DBNull Exception from datatable row - vb.net

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

Related

Set DateTimePicker time format value to value returned from database VB.NET

Would appreciate assistance on the below.
I am using VB.NET and SQL Server.
I have a form with a datagridview, when the user clicks one of the rows (Header rows) on the datagridview the form shows the detail for the header in text boxes, comboboxes and datetimepickers allowing the user to edit the detail values and saving back to the database.
I am having trouble returning the times saved in my database to the datetimepickers, they default to the current system time and do not return the saved time in the Database:
I am using a datetimepicker format set to "Time" so the actual date is irrelevant, only the time.
I have tried the below in my Datagridview_CellContentClick event:
Dim dr As DataRowView = GetStoreMasterBindingSource.Current
WeekStartTimeDateTimePicker.Text = dr.Item("WeekStartTime").Value
But get the following error at runtime:
Public member 'Value' on type 'Timespan' not found.
I have also tried the following:
Dim dr As DataRowView = GetStoreMasterBindingSource.Current
WeekStartTimeDateTimePicker.Value = New DateTime(DateTime.Now.Year, DateTime.Now.Month,
DateTime.Now.Day, dr.Item("WeekStartTime").hour,
dr.Item("WeekStartTime").minute,
dr.Item("WeekStartTime").second)
But get the following error at runtime:
Public member 'hour' on type 'Timespan' not found.
My SQL datatype for this column is TIME.
Please assist me to set the time value of my datatimepicker to the value returned from the database?
Dim currentRow = DirectCast(GetStoreMasterBindingSource.Current, DataRowView)
WeekStartTimeDateTimePicker.Value = Date.Today + DirectCast(currentRow("WeekStartTime"), TimeSpan)

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

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)

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.

How to Sort datagridview by column values which are of datetime type.?

I have a problem while sorting datagridview by column2 (name of the column i used )
i used datetime type values in the column and now i want to sort the grid ( named as conv_msg_grid) by using following command
conv_msg_grid.Sort(Column2, System.ComponentModel.ListSortDirection.Ascending)
but it is giving an error " Object must be of type String."
what is wrong in it???
please help me out.....
Seems like you have inconsistent datatypes in your table. Your first item(s) are of type string, but some of them are of type date. So when you try to sort and you hit something which isn't a string this error occurs.
To solve it you have two options.
Before sorting turn everything into datetime (or string) values. (This is the better choice if the user is allowed to add dates)
When inserting data into the DatagridView you make sure that all the values are of DateTime (or string). (This is the better choice if the user can't type in dates)
To do the (or string) option simply remove convert.ToDateTime and do ToString on value.
Dim Column2 As DataGridViewColumn = DataGridView1.Columns(0)
For Each r As DataGridViewRow In DataGridView1.Rows
r.Cells(Column2.Index).Value = Convert.ToDateTime(r.Cells(Column2.Index).Value)
Next
conv_msg_grid.Sort(conv_msg_grid.columns(2), System.ComponentModel.ListSortDirection.Ascending)
Kalunche

DataTable Select(String) Function Help VB .NET

I made a datatable with 2 columns a transactionTime column and a numberOfTransactions column. I made the table with the pre-defined transaction times and want to add the number of transactions from an XML file. I have gotten through the XML file and want to add the data to the correct row. Here is the function:
Function AddRow(ByVal timeOfTransaction As String, ByVal numberOfTransactions As String, ByRef dataTableOfTransactions As DataTable) As String
Dim row() As DataRow = dataTableOfTransactions.Select("transactionTime = timeOfTransaction")
If row(0) IsNot Nothing Then
row(0)("numberOfTransactions") = numberOfTransactions
End If
Return Nothing
End Function
When I run this it overwrites the first element in the table's numberOfTransactions coloumn. I know it has to do with the "transactionTime = timeOfTransaction" part but I can't seem to get it to read timeOfTransaction as a reference to a string instead of a literal. Any help would be much appreciated. Thanks!
You need to write something like this :
Dim row() As DataRow = dataTableOfTransactions.Select("transactionTime=#" & timeOfTransaction & "#")
But be careful with your date/month or month/date format, it depends of your regional settings.
row(0)("numberOfTransactions") = numberOfTransactions
Right there you are telling the program to overwrite that value with number of transactions.
If you want that value you need to set it to something, not set something to it.
Also, if you want your select to work properly try doing it like this
dataTableOfTransactions.Select("transactionTime = " + timeOfTransaction)