Simple way to convert dbNull to a string in VB.NET - vb.net

I'm looking for a simpler way to check if a value is dbNull and to convert it to an empty string if so.
An example of a situation where I need this would be:
Dim dt As New DataTable
Dim conn As New OleDbConnection(someConnStr)
Dim adap As New OleDbDataAdapter(qryCSSInfo, cssConn)
adap.Fill(dt)
Dim someStr As String = "The first column of the first row returned: " & dt.rows(0).item(0)
Msgbox(someStr)
The problem is that if dt.rows(0).item(0) is null in the database it will be returned as a dbNull value, which can apparently not be appended to a string.
My solution to this problem has been using if statements to replace the value with blank strings:
Dim dt As New DataTable
Dim conn As New OleDbConnection(someConnStr)
Dim adap As New OleDbDataAdapter(qryCSSInfo, cssConn)
adap.Fill(dt)
If Not isDBNull(dt.rows(0).item(0)) then
Dim someStr As String = "The first column of the first row returned: " & dt.rows(0).item(0)
Else
Dim someStr As String = "The first column of the first row returned: " & ""
End If
Msgbox(someStr)
This works fine for my purposes, but it gets overwhelming if I have to make this check for every column I need to use in the table. Say I had 10 columns from the table that I wanted to display with this string. I'd have to make this check on each one to ensure they weren't null. Is there an easier or simpler way of doing so?

For string types you can directly use it this way dt.rows(0).item(0).ToString(), without the If condition
adap.Fill(dt)
Dim someStr As String = "The first column of the first row returned: " & dt.rows(0).item(0).ToString()
MsgBox(somestr)
i.e. you can completely omit the if statement. As per MSDN any DBNull value will be converted to EmptyString with .ToString()
Also check this SO post Conversion from type 'DBNull' to type 'String'
However, for non-string database column types such as integers, doubles you must apply checks using IsDBNull to avoid any exceptions.

You can leverage the If Operator to reduce a few lines of code:
Dim someStr As String = "The first column of the first row returned: " & _
If(dt.rows(0).item(0) Is DbNull.Value, String.Empty, dt.rows(0).item(0))

You should be able to concatenate a null field with a string - it should convert to an empty string. That said row.IsNull(index) is a good test to use.
SQL = "Select top 10 Region, CompanyName FROM Suppliers"
Dim dt As DataTable = Gen.GetDataTable(SQL, scon)
For Each row As DataRow In dt.Rows
MsgBox(row("companyName") & " region: " & row("Region")) ' null allowed
If row.IsNull("region") Then ' .Net test for Null
MsgBox(row("companyName") & " region is null")
Else
'continue
End If
Next
You can also resolve this in the query - covert nulls to useful (or empty) strings. The example query is from SQL Server, I don't know if your DB supports COALESCE.
MsgBox("COALESCE") ' SQL Server - may not be the same in ODBC databases
SQL = "Select top 10 COALESCE(Region,'na') Region, CompanyName FROM Suppliers"
dt = Gen.GetDataTable(SQL, scon)
For Each row As DataRow In dt.Rows
MsgBox(row("companyName") & " region: " & row("Region"))
Next
Some coding notes:
Dim dt As New DataTable
Dim conn As New OleDbConnection(someConnStr)
Dim adap As New OleDbDataAdapter(qryCSSInfo, cssConn)
adap.Fill(dt)
If Not IsDBNull(dt.Rows(0).Item(0)) Then ' in OP
'...
End If
' save some typing if you know there will be only one record
' will throw exception is no rows are returned, check for expected count
Dim row As DataRow = dt.Rows(0)
If Not IsDBNull(row(0)) Then
'...
End If
' or
If Not row.IsNull(0) Then
'...
End If
' note the fields can be accessed by name so you can avoid hard coding field position
If Not row.IsNull("FieldName") Then
'...
End If

The simplest way to do it is just add a "" after the field or string.
Eg.:
dim EmptyString as string = Nullfield() & ""
if EmptyString = ""
' in the sample, it should.
end if
So, in your code you can use:
If dt.rows(0).item(0) & "" = "" then
' it should be...
end if

I got some null data into cells of a datagrid; to correctly retrieve that data
I concatenate the "" string to the cell value:
Dim readVal As String = "" & row.Cells(2).Value

Related

Is there a way to run a for loop query based on datagridview selected values in vb.net?

Unable to get the excepted result due to the following error
Conversion from string " to type 'integer' is not valid'
I have been able to load values from the products table, add selected ones to Selected Products and then search all the selected products against the Customers table to find out how many customers ordered these products.
Try
Dim ListOfDiag As StringBuilder = New StringBuilder()
For Each row As DataGridViewRow In SelectedDiagDGV.Rows
ListOfDiag.Append(row.Cells(0).Value.ToString & "", "" & Environment.NewLine)
Next
Dim query As String = String.Empty
Dim SegmentConnectionString As String = "Data Source=Test-PC;Initial Catalog=TestDB;Integrated Security=True"
query = "SELECT Customers, ProductName from Customers WHERE ProductName in (" & ListOfDiag.ToString & ")"
Dim dTable As DataTable = New DataTable()
Dim dAdapter As SqlDataAdapter
dAdapter = New SqlDataAdapter(query, SegmentConnectionString)
dAdapter.Fill(dTable)
DataGridView1.DataSource = dTable
'Next
Catch ex As System. Exception
MsgBox(ex.Message.ToString)
End Try
Unable to perform a for loop search. Some of the values contain special characters example: Soft ’Drink’; Computer (Desk).
Error: Conversion from string " to type 'Integer' is not valid.
ListOfDiag.Append(row.Cells(0).Value.ToString & "", "" & Environment.NewLine)
There is no overload of StringBuilder.Append that takes (String, String) as arguments. the first string is row.Cells(0).Value.ToString & "" and then there is a comma between parameters and the second string is "" & Environment.NewLine Remember that "" is an empty string, not escape characters. Not sure what your intention was but this will not work.
You had the right approach; to build a string for the In clause. I used a List(Of String) to get the data from the rows then after the loop I used a .Join with a comma separator to get the value for the In clause.
I passed the connection string directly to the constructor of the Connection and passed the Select statement and the connection to the constructor of the Command. For the Select statement I used and Interpolated String (the string preceded by the $) You could also use String.Format in older version of Visual Studio.
The Using...End Using blocks ensure that your database objects are closed and disposed even if there is an error.
I think the only special character that could mess things up would be the presence of a comma in a Product Name.
Private Sub OPCode()
Dim dTable As New DataTable
Dim ListOfDiag As New List(Of String)
For Each row As DataGridViewRow In SelectedDiagDGV.Rows
ListOfDiag.Add(row.Cells(0).Value.ToString)
Next
Dim InData = String.Join(",", ListOfDiag)
Using cn As New SqlConnection("Data Source=Test-PC;Initial Catalog=TestDB;Integrated Security=True")
Using cmd As New SqlCommand($"SELECT Customers, ProductName from Customers WHERE ProductName in ({InData})", cn)
cn.Open()
dTable.Load(cmd.ExecuteReader)
End Using
End Using
DataGridView1.DataSource = dTable
End Sub

Converting Display Member Property to Upper Case

I'm using the following query to return results from an access database. Within the column "DocName" there is a mix of strings that are Upper Case, Lower Case & and combination of both. Unfortunately I do not have access to amend the database so would like to convert the "Display Member" to ideally Proper Case but if not possible Upper Case. I have seen the .ToUpper options but can't get it to work. Any Ideas
Dim da As New OleDb.OleDbDataAdapter("", "")
Dim dt As New DataTable
Dim conn As String
Dim eSearch As String = AllDetails(n).uCode
conn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Me.aClients & ""
da.SelectCommand.Connection.ConnectionString = conn
da.SelectCommand.CommandText = "SELECT DocName FROM Documents WHERE (UnitCode = " & eSearch & ") AND (Required = True)"
da.Fill(dt)
lstRequired.DataSource = dt
lstRequired.DisplayMember = "DocName"
lstRequired.Refresh()
Exit Sub
End If
Next
End Sub
Try this as the query in your command:
da.SelectCommand.CommandText = "SELECT UCASE(DocName) AS DocNm FROM Documents WHERE (UnitCode = " & eSearch & ") AND (Required = True)"
There is a UCase function that retrieves all data in upper case if it is a string.
Update: Based on your comment to another question, now your returned column is no longer named DocName. Use the line of code above to replace your code that sets the command text, and then replace your line of code that sets the DisplayMember property with the line of code below:
lstRequired.DisplayMember = "DocNm"
I explicitly set the column name to DocNm of your newly-created column and changed the DisplayMember property to the new column name.
you can do it at the commandtext or iterate through the table and update each row's DocName column with .ToUpper().
I believe with that provider you can use uCASE
da.SelectCommand.CommandText = "SELECT UCASE(DocName) as DocName FROM Documents WHERE (UnitCode = " & eSearch & ") AND (Required = True)"
if not UCASE try UPPER(DocName) as DocName

"No data exists for the row/column" when connecting to SQL database from VB.net

I'm trying to create a program which has a datagridview, when the user clicks on a cell in the view, it then looks in a SQL database, grabs information from other fields in the same record, and automatically fills corresponding text boxes (done by manipulating the name of the field) in the form.
For some reason however, I'm getting an error message saying:
"InvalidOperationException was unhandled"
"No Data exists for the row / column"
Here is the code relevant to this part of the program:
Private Sub DataGridView1_CellMouseClick(sender As Object, e As DataGridViewCellMouseEventArgs) Handles dgvResults.CellMouseClick
' Set values in the text boxes to both corresponding to the film.
Dim strFields() As String = {"ID", "fName", "fGenre", "fSynopsis", "fAgeRating", "fActorsActresses", "fWebRating", "fNoReservations", "fWeeksRunning"}
Dim Con = New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=ApplicationData.accdb;Persist Security Info=False;")
Con.Open() 'Open the connection
Dim Cmd As New OleDbCommand(StringBuilderCommand("*", "Films", dgvResults.CurrentCell.Value, "fName"), Con) 'Create a string by calling the StringBuilderCommand to combine the parameters together with quotes.
Cmd.CommandType = CommandType.Text
Dim Rdr As OleDbDataReader = Cmd.ExecuteReader()
Dim intCount As Integer = 4 ' Create a loop variable.
Do While Rdr.Read() Or intCount < 6 ' While this statement is 'TRUE', e.g. there is a valid record.
strResult = "txt" & strFields(intCount).Replace("f", "") 'Remove any instances of 'f', e.g. the prefix of the string.
txtActorsActresses.Text = StringBuilderCommand("*", "Films", dgvResults.CurrentCell.Value, "fName")
Me.Controls(strResult).Text = Rdr.Item(strFields(intCount)) ' Suspect the error lies here.
'Set the text-box to the correct value from the database.
'This will allow me to go through several text boxes, and grab their corresponding values from the database.
intCount = intCount + 1
'Current error is because it cannot find any data beyond the first field taken.
'I have no idea why this is. But if I change the starting intCount value, it will successfully take a different value.
Loop
Rdr.Close() 'Cleaning up.
Cmd.Dispose()
Con.Close()
WebBrowser1.Navigate(dgvResults.CurrentCell.Value.Replace(" ", ".") & ".movie.poster.new.jpg.to") 'Grab the movie poster off the internet corresponding to the films name.
End Sub
Private Function StringBuilderCommand(Field, Table, CurrentCellValue, SearchParameter)
'Creates a suitable SQL string.
Dim MyStringBuilder As New StringBuilder("SELECT ")
MyStringBuilder.Append("*") ' Append the parameter 'Field'.
MyStringBuilder.Append(" FROM ") ' Append the SQL command 'FROM'.
MyStringBuilder.Append(Table) ' Append the parameter 'Table'.
MyStringBuilder.Append(" WHERE ") ' Append the SQL command 'WHERE'.
MyStringBuilder.Append(SearchParameter) ' Append the parameter 'SearchParameter'.
MyStringBuilder.Append("=""")
MyStringBuilder.Append(CurrentCellValue) ' Append the parameter 'CurrentCellValue', representing the cell selected.
MyStringBuilder.Append("""") 'Append a quotation mark.
Return MyStringBuilder.ToString() ' Return it to the main program.
End Function
Database table being connected to:
A view of the error as it looks in Visual Studio 2012 Express:
The value of 'dgvResults.CurrentCell.Value' is the name of a film taken from the database (e.g. "12 Years a Slave").
What am I doing wrong?
Thanks,
C.
The problem is caused by the value of strFields(intCount) you are passing to the reader. It is not a valid column index.
You probably want to loop on the fields before looping again on DataReader(), like:
Do While Rdr.Read()
For intCount as Integer = 4 to 6
strResult = "txt" & strFields(intCount).Replace("f", "")
txtActorsActresses.Text = StringBuilderCommand("*", "Films", dgvResults.CurrentCell.Value, "fName")
Me.Controls(strResult).Text = Rdr.Item(strFields(intCount))
Next
Loop
I removed the Dim intCount As Integer = 4 because it is no longer needed because of the for next loop.

VB.net table iteration

I have this code now. But it fails at three steps. Can you help me figure this out??
I have listed the three points where it fails.
Also please validate for me If I'm doing it right?
Retrieve the string from the tb_metatags textbox
Dim s As String
s = Me!tb_metaatags
parse the string into substrings by looking for the commasDim arrLines() As String
Dim arrLines() As String
arrLines = Split(s, ",")
For each substring, check if the substring is in the MetaSearchTags table
Dim itm As Variant
For Each itm In arrLines
Dim strsql As String
Dim numrows As Integer
strsql = "SELECT COUNT(*) FROM MetaSearchTags WHERE SearchTag = " & itm & ""
Dim objcmd As New OleDbCommand(strsql, conn) "I get an error here
numrows = objcmd.ExecuteScalar
If numrows > 0 Then
MsgBox("Record Exists", vbInformation, "Add") "I get an error here
Else
Dim myadapter1 As New OleDbDataAdapter("INSERT INTO MetaSearchTags ( SearchTag) "VALUES ('" & itm & "')", conn) "I get an error here
Dim mytable1 As New DataTable
myadapter1.Fill (mytable1)
End If
if it is not already in the MetaSearchTags table, then add it to the table
get the primary key (ID) for the substring from the MetaSearchTags table
Add an row in the MetaSearchTagAssignments table for this search tag
using the projectID, and the substring ID from the MetaSearchTags table
Repeat this process for each substring entered in the field
OleDbCommand.ExecuteScalar returns
The first column of the first row in the result set, or a null
reference if the result set is empty.
You need to handle this null reference (in VB.NET this equates to Nothing) when no records are returned.
One way to do this is:
Dim numrows as String = String.Empty
numrows = objcmd.ExecuteScalar()
If numrows Is Nothing Then
'Do something with the error condition
Else
'Do something with numrows which contains a valid result.
End If
(I would rename numrows)
You are also attempting to insert a record into the table even though no results are returned. This wouldn't be an error, but you have indicated (although it is a little difficult to interpret) that SearchTag is a primary key, in which case it will be an error to attempt to insert a duplicate.
And, as mentioned, you need to correct the quotes and apostrophes for your INSERT statement.
You need to put single quotes around strings in SQL statements:
strsql = "SELECT COUNT(*) FROM MetaSearchTags WHERE SearchTag = " & itm & ""
Should be:
strsql = "SELECT COUNT(*) FROM MetaSearchTags WHERE SearchTag = '" & itm & "'"

Update in new column after inserting into 2 columns in a db

I am using following code to insert records into a table from another table....
Private Sub InsDuplicateDB()
Dim strInsDup As String = "INSERT INTO Duplicate_srno(Sr_no,chalan_no) SELECT sr_no,chaln_no FROM Vendor_Machine where sr_no=#srno"
Dim comm_InsDup As OleDb.OleDbCommand = New OleDb.OleDbCommand(strInsDup, cnnOLEDB)
comm_InsDup.Parameters.AddWithValue("#srno", cmbSn_no.Text)
comm_InsDup.ExecuteNonQuery()
Dim strUpdDup As String = "UPDATE Duplicate_srno SET sr_no = #srno,chaln_no =#chn_no,Problem=#problemWHERE sr_no = #srno AND chalan_no=#chn_no"
Dim comm_Update As OleDb.OleDbCommand = New OleDb.OleDbCommand(strUpdDup, cnnOLEDB)
comm_Update.Parameters.AddWithValue("#srno", cmbSn_no.Text)
comm_Update.Parameters.AddWithValue("#chn_no", cmbChal_no.Text)
comm_Update.Parameters.AddWithValue("#problem",strProb)
comm_Update.ExecuteNonQuery()
End Sub
Here strProb is a string whose value is assigned in anoter sub function..
Here it gives error as "No values given for one or more required parameter.."
Please resolve my problem
I don't know if this is a typo or not, but the update string lacks of a space between the parameter name #problem and the WHERE clause
Dim strUpdDup As String = "UPDATE Duplicate_srno SET sr_no = #srno,chaln_no =#chn_no," & _
"Problem=#problem WHERE sr_no = #srno AND chalan_no=#chn_no"
^
However the update string could be simplified because you are updating two fields with the same values used in the where clause
Dim strUpdDup As String = "UPDATE Duplicate_srno SET Problem=#problem " & _
"WHERE sr_no = #srno AND chalan_no=#chn_no"
Apart from the missing space the error message says that the engine expects more parameters.
In OleDb the parameters are not recognized by their name. You need the same number of parameter that are defined by the placeholders in the string. In your original text, you have 5 placeholders but you add only 3 parameters. It doesn't matter if two of them are the same.
The revised code coould be the following
Dim strUpdDup As String = "UPDATE Duplicate_srno SET Problem=#problem " & _
"WHERE sr_no = #srno AND chalan_no=#chn_no"
Dim comm_Update As OleDb.OleDbCommand = New OleDb.OleDbCommand(strUpdDup, cnnOLEDB)
comm_Update.Parameters.AddWithValue("#problem",strProb)
comm_Update.Parameters.AddWithValue("#srno", cmbSn_no.Text)
comm_Update.Parameters.AddWithValue("#chn_no", cmbChal_no.Text)
Notice how I have added the #problem parameter as first in the collection. Now, the parameter collection is in the same order in which the placeholders are present in the command text.