ExecuteReader error when selecting multiple columns "No data exists for row/column" - vb.net

I am trying to run a simple query that returns three columns but am running into an error stating that the data does not exist though I am quite certain it does.
This is the section of code in question.
cmd.CommandText = "SELECT school.id, school.city, school.state
FROM school,city
WHERE school.name = '" & SchoolLb.SelectedItem & "'
AND city.name = '" & CityLb.SelectedItem & "';"
'MessageBox.Show(cmd.ExecuteScalar)
myReader = cmd.ExecuteReader
profileSchool = myReader(0)
profileCity = myReader(1)
profileState = myReader(2)
The School list box is populated with schools located in the city that is currently selected in the city list box, so they match up. When I remove the comment tag from MessageBox.Show(cmd.ExecuteScalar) the ExecuteScalar runs and returns a message showing the ID of the correct record. However when using cmd.ExecuteReader I get the error mentioned above.
Thanks for looking.

You need to execute the reader and then advance it to the next record by using reader.Read():
Using reader = cmd.ExecuteReader()
reader.Read()
profileSchool = reader(0)
profileCity = reader(1)
profileState = reader(2)
End Using

Related

Looping through SqlDataReader returns same row twice

I'm making a VB.NET (4.6) Windows form application that collects info on our servers and allows us to do reports on it. It's coming together nicely but I've run into an issue I can't figure out. One part of the project is a service that queries the info on available Windows updates from WSUS and then stores them in an SQL database - that part works fine. I'm now trying to present this data in a DataGridView using an SqlDataReader to query the info from the database and fill up a DataTable with the response. The problem is that when I use the reader, it puts the same record in the DataTable twice. I'm not sure what I'm doing wrong, and I'm sure it's something super simple. Perhaps one of you folks can spot the problem?
Note: Earlier in the application, the updateid's are stored as unique strings in a list called dbupdateidlist, the results are stored in a DataTable called dbupTable, and the datagridview I'm trying to update is called UpdateDeetsView.
Public Sub getUpdateDetails()
For Each str As String In dbupdateidlist
Dim commGetUpdateDetails As String = "select upTableId, title, classification, description, " +
"releasedate, severity, articlenumber, url from updatedetails where updateid = '" + str + "'"
Using connObj As New SqlClient.SqlConnection(connectionString)
Using cmdObj As New SqlClient.SqlCommand(commGetUpdateDetails, connObj)
connObj.Open()
Using readerObj As SqlClient.SqlDataReader = cmdObj.ExecuteReader
While readerObj.Read
dbuptabid = readerObj("uptableid")
dbuptitle = readerObj("title")
dbupclass = readerObj("classification")
dbupdesc = readerObj("description")
dbupreleasedate = readerObj("releasedate")
dbupseverity = readerObj("severity")
dbuparticlenumber = readerObj("articlenumber")
dbupurl = readerObj("url")
row = dbupTable.NewRow()
row("uptableid") = dbuptabid
row("title") = dbuptitle
row("classification") = dbupclass
row("description") = dbupdesc
row("releasedate") = dbupreleasedate
row("severity") = dbupseverity
row("articlenumber") = dbuparticlenumber
row("url") = dbupurl
dbupTable.Rows.Add(row)
End While
End Using
connObj.Close()
End Using
End Using
Next
UpdateDeetsView.DataSource = dbupTable
End Sub
Forgive the likely terrible code, I'm an SA not a dev...
Try this:
Public Sub getUpdateDetails()
Dim sql As String = _
"SELECT DISTINCT upTableId, title, classification, description, releasedate, " & _
" severity, articlenumber, url " & _
" FROM updatedetails " & _
" WHERE updateid = #updateID"
Using cn As New SqlClient.SqlConnection(connectionString), _
cmd As New SqlClient.SqlCommand(sql, cn)
cmd.Parameters.Add("#updateID", SqlDbType.Int).Value = Int32.Parse(dbupdateidlist.First())
cn.Open()
UpdateDeetsView.DataSource = cmd.ExecuteReader()
End Using
End Sub
Note the use of DISTINCT and the complete lack of any explicit loops whatsoever.
Also note that I'm only looking at one entry in dbupdateidlist. The real source of your old bug may have been to have the the ID in that list twice.
There is no way readerObj.Read is failing to move to the next record
get the output of this and run it is SSMS
"select upTableId, title, classification, description, " +
"releasedate, severity, articlenumber, url from updatedetails where updateid = '" + str + "'"

Displaying multiple rows in multiple textboxes

I have a SQL Database table with multiple rows. I want to get the data from the rows based on the ID of that row and then present it in a certain textbox. I've got it working with Access 2013, but i've recently decided to move it to SQL.
I get an error
"There is already an open Datareader associated with this command"
Before i show you the code, it's pretty simplistic. I kind of "made" it work with access 2013, but SQL doesn't like it. The way the APP works it is paramount to have the data displayed in textboxes to make it easier to amend the data whilst being able to tab to the next box efficiently. That's why i haven't used Gridview. well, i have but that is for an asset register which is fine.
The code:
Try
conn.Open()
'***************** Populate Textboxes based on ID 1 row of PrinterDetails ***************** '
Dim sql1 As String
sql1 = "select * from PrinterDetails where ID=1"
cmd = New SQLCommand(sql1, conn)
reader = cmd.ExecuteReader
While reader.Read
'' Convert to string to prevent DBNULL errors
SNAME1.Text = reader.Item("SiteName").ToString
MAKE1.Text = reader.Item("Make").ToString
MODEL1.Text = reader.Item("Model").ToString
PRINTERIP1.Text = reader.Item("PrinterIP").ToString
PSERVER1.Text = reader.Item("Server").ToString
SHARE1.Text = reader.Item("Share").ToString
LOC1.Text = reader.Item("Location").ToString
UN1.Text = reader.Item("Username").ToString
PASS1.Text = reader.Item("Password").ToString
SUPPORT1.Text = reader.Item("Support").ToString
End While
'***************** Populate Textboxes based on ID 2 row of PrinterDetails ***************** '
Dim sql2 As String
sql2 = "select * from PrinterDetails where ID=2"
cmd = New SQLCommand(sql2, conn)
reader = cmd.ExecuteReader
While reader.Read
'' Convert to string to prevent DBNULL errors
SNAME2.Text = reader.Item("SiteName").ToString
MAKE2.Text = reader.Item("Make").ToString
MODEL2.Text = reader.Item("Model").ToString
PRINTERIP2.Text = reader.Item("PrinterIP").ToString
PSERVER2.Text = reader.Item("Server").ToString
SHARE2.Text = reader.Item("Share").ToString
LOC2.Text = reader.Item("Location").ToString
UN2.Text = reader.Item("Username").ToString
PASS2.Text = reader.Item("Password").ToString
SUPPORT2.Text = reader.Item("Support").ToString
End While
I've tried closing the connection and re-opening but that doesn't work.
Why such a bizarre query and code; your SQL query can simply be like below using a IN operator
select * from PrinterDetails where ID in (1,2);
BTW, for your issue check This MSDN Link specifically the Remarks section. In essence, you will need to close the already opened reader.

how validate if record not found on database in vb.net

how make sure if record not found when sql query using where not get the result.
i use this source and work for display record if record found, but i don't know how use "if then else" for change the "while"
Sub usercheck()
'Prepare Connection and Query
dbconn = New MySqlConnection("Server=localhost;Database=user_team;Uid=root;Pwd=")
strQuery = "SELECT * " & _
"FROM tb_team_user WHERE user_ip = '" & lip.Text & "'"
SQLCmd = New MySqlCommand(strQuery, dbconn)
'OPEN THE DB AND KICKOFF THE QUERY
dbconn.Open()
DR = SQLCmd.ExecuteReader
While DR.Read
tbteam.Text = DR.Item("user_team")
End While
End Sub
Before your while loop, you can add an if statement to see if there are any rows returned:
If DR.HasRows Then
' There was at least 1 row returned
Else
' There were no rows returned
End If

Create report from Bound DataTable

I'm fairly new to programming.
I don't plan on using Crystal Reports unless it is absolutely necessary because of license fees. I have also looked into .rdlc a little bit and to be honest it confused me. I was not sure how to get the data I wanted into the Client Report Definition using the Report Wizard. As a side note, though, I am dealing with encrypted data.
I am decrypting data in my DataTable, and would like to make a report out of the DataTable that feeds a DGV and show it in a ReportViewer. If there is a better way please let me know!
I am not sure how to use the DataTable as the data source for the report. Here ismy code for both:
Dim dt As DataTable = ds.Tables(1)
ds.DataSetName = "DataSetReport"
dt.TableName = "DataTable1"
If SearchFirsttxt.Text = "" Then
SqlCommand.CommandText = "Select * FROM PARTICIPANT WHERE LAST_NM_TXT = '" & eLast & "';"
ElseIf SearchLastTxt.Text = "" Then
SqlCommand.CommandText = "Select * FROM PARTICIPANT WHERE FIRST_NM_TXT = '" & eFirst & "';"
Else
SqlCommand.CommandText = "Select * FROM PARTICIPANT WHERE FIRST_NM_TXT = '" & eFirst & "' and LAST_NM_TXT = '" & eLast & "';"
End If
'SQL Command returns rows where values in database and textboxes are equal
SearchFirsttxt.Text = ""
SearchLastTxt.Text = ""
dFirst = clsEncrypt.DecryptData(eFirst) 'Decrypts the value entered into the SearchFirsttxt
dLast = clsEncrypt.DecryptData(eLast) 'Decrypts the value entered into the SearchLasttxt
Dim myAdapter As New SqlDataAdapter(SqlCommand) 'holds the data
myAdapter.Fill(dt) 'datatable that is populated into the holder (DataAdapter)
DataGridView1.DataSource = dt 'Assigns source of information to the gridview (DataTable)
Try
For i As Integer = 0 To dt.Rows.Count - 1
dt.Rows(i)("FIRST_NM_TXT") = clsEncrypt.DecryptData(dt.Rows(i)("FIRST_NM_TXT"))
dt.Rows(i)("LAST_NM_TXT") = clsEncrypt.DecryptData(dt.Rows(i)("LAST_NM_TXT"))
Next
Catch ex As Exception
MessageBox.Show("Either the first name or last name did not match. Please check your spelling.")
End Try
I've tried:
Dim ds As DSReportTest
ds.Tables.Add(dt)
which didn't work. The reason I am trying to rely on dt is because it contains the decrypted data.
Printing DataGridView using PrintDocument could be tedious. Refer this codeproject article to get an idea.
You can also use the DataGridView clipboard content to get the formatted values into clipboard and copy into some excel file. The below MSDN link has some example for getting clipboard content from DataGridView.
http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.getclipboardcontent%28v=vs.110%29.aspx
If you are using vs 2010, you should not have a license issue using crystal reports when deploying an application. I assume it's not server based redistribution.
http://www.sap.com/solution/sme/software/analytics/crystal-visual-studio/implement/licensing.html

SqlDataReader getting rows when no data

This is incredibly urgent, I need to present this application in 3 and a half hours.
My application checks against a data source to see if a value exists in the database and changes values depending on whether or not the value in question was found.
The problem is that I've run the sql query with the value in question in SSMS and no rows were returned, and yet, my DataReader says it has rows.
This means that my application is reporting inaccurately.
Here's my code:
Using conn As New SqlConnection("Data Source=.\SQLEXPRESS; Initial Catalog=Testing; Integrated Security=True;")
Dim cmd As New SqlCommand(sql, conn)
conn.Open()
Dim reader As SqlDataReader = cmd.ExecuteReader
If reader.HasRows Then
Value = True
AcctNumber = reader(1)
End If
reader.Close()
End Using
I've removed code that's not relevant to this post, but what you may want to know is:
Value is Boolean
AcctNumber is a String
As this is an application for work, I'd rather not include the SQL Query. The problem is the reader. If I comment out Value = True, I get the right info, but leaving that out will mean that in a case where Value should be True, it'll report inaccurately as well.
Thanks in advance!
EDIT: Full Source Code:
Case "Business"
' Change the number format to local because that's what it is in the db
If Microsoft.VisualBasic.Left(NumberToCheck, 2) = "27" Then
NumberToCheck = NumberToCheck.Replace(Microsoft.VisualBasic.Left(NumberToCheck, 2), "0")
End If
Dim sql As String = "SELECT a.TelNumber, c.AccountNumber " & _
"FROM TelInfo a " & _
"INNER JOIN Customers b ON a.CustID = b.pkguidId " & _
"INNER JOIN Accounts c ON b.pkguidId = c.CustID " & _
"WHERE a.TelNumber = '" & NumberToCheck & "'"
Using conn As New SqlConnection("Data Source=.\SQLEXPRESS; Initial Catalog=Testing; Persist Security Info=True; " & _
"User Id=JoeSoap; Password=paoseoj;")
Dim cmd As New SqlCommand(sql, conn)
conn.Open()
Dim reader As SqlDataReader = cmd.ExecuteReader
If reader.Read Then
Value = True
AcctNumber = reader(1)
End If
reader.Close()
End Using
On the comments below made before 08/02/10 (mm/dd/yy):
Value is just a boolean that gets returned by the function to indicate that the searched telephone number (NumberToCheck) exists in the database.
So...
Private AcctNumber As String
Dim val As Boolean = False
val = CheckNumber("3235553469")
If val Then
' AcctNumber will have been set by CheckNumber
Label1.Text = AcctNumber
End If
val will only be returned True if the NumberToCheck (in this example 3235553469) exists in the database.
Having copied the value of NumberToCheck into SSMS and testing the query there, I can verify that the query does work as expected.
No, I can't populate a DataSet because of the volume of information in the table (+/- 9.5m rows). Even with the 'WHERE' filter, the query is too heavy on resources and eventually ends in an OutOfMemory Exception which is why I went with a DataReader.
I'm going to try the ExecuteScalar option as suggested as an answer by Darryl now, will update with the results.
Try changing your If statement to
If reader.Read() Then
Value = True
AcctNumber = reader(1)
End If
HasRows exhibits strange behavior in certain situations, so it's better to avoid it altogether.
This does not solve the problem, but it may get you through your presentation. Use "ExecuteScalar" which should work when you return a single value.
AcctNumber = ""
AcctNumber = cmd.ExecuteScalar
If AcctNumber = "" Then
Value = False
Else
Value = True
End If
Just to be sure it's not a data problem, parameterize your SQL. Change the statement:
Dim sql As String = "SELECT a.TelNumber, c.AccountNumber " & _
"FROM TelInfo a " & _
"INNER JOIN Customers b ON a.CustID = b.pkguidId " & _
"INNER JOIN Accounts c ON b.pkguidId = c.CustID " & _
"WHERE a.TelNumber = #telNumber"
Then do this:
Dim cmd As New SqlCommand(sql, conn)
cmd.Parameters.AddWithValue("#telNumber", NumberToCheck) ' <==== added line
Edit
I think we're looking in the wrong place. Add this just before if reader.Read():
Value = false
AcctNumber = ""
This will make sure you're not having a variable-scope problem. (You are using Option Strict On, right?)
In the immortal words of Homer Simpson... "DOH!!"
I just had a look on the database that my application searches for the telephone numbers and, I don't know how I could have missed it, but the value I'm searching for is actually there.
The problem is, therefore, not likely anything to do with my code, but rather the data...