Pull value from SQL Server in VB.NET - sql-server

I am attempting to pull values from an SQL Server table from VB.NET.
On VB Form 1, the number from NoTable, Row 1, is pulled successfully, and Label1 is updated with the value.
Dim command As SqlCommand
Dim query As String = "SELECT Number FROM NoTable"
command = New SqlCommand(query, con)
con.Open()
Dim datareader As SqlDataReader = cmd.ExecuteReader()
If datareader.Read() Then
Label1.Text = datareader.GetValue(0)
End If
datareader.Close()
On VB Form 2 I am attempting to pull the value from the second row, using:
Dim query As String = "SELECT Number FROM NoTable"
command = New SqlCommand(query, con)
con.Open()
Dim datareader As SqlDataReader = cmd.ExecuteReader()
If datareader.Read() Then
Label1.Text = datareader.GetValue(1)
End If
datareader.Close()
However, this does not work, and the label is not updated with the value from the second row.
An unhandled exception of type 'System.IndexOutOfRangeException' occurred in System.Data.dll
Additional information: Index was outside the bounds of the array."
How would I go about fixing this, so that on Form 2, the value from Row 2 is pulled, and so forth?
Thank you.

Firstly, you only get one column back from the reader, but you are indexing the columns with that 0 or 1. So you should always pass 0 to GetValue.
To index the row instead, try this. Assign a form number to each form (first line in my example) and use that to determine which record to assign to the Label. There is probably a more efficient way to do this (not returning all the records before it) but this solution should fit in your environment.
' in form # 1
Dim formNumber = 1
Dim command As SqlCommand
Dim query As String = "SELECT Number FROM NoTable"
command = New SqlCommand(query, con)
con.Open()
Dim datareader As SqlDataReader = cmd.ExecuteReader()
Dim index = 0
While index < formNumber
If datareader.Read() AndAlso index = formNumber Then
Label1.Text = datareader.GetValue(0)
End If
index += 1
End While
datareader.Close()
See https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.getvalue(v=vs.110).aspx
And another similar question in c# Access a specific row in DataReader
Another way is to just return the row you need in the first place, without iterating over the records on the client side. Assuming there is another column with an index which is in the same order as the row you want to return, called "ID"
' in form # 1
Dim formNumber = 1
Dim command As SqlCommand
Dim query As String =
"SELECT Number FROM " & _
" (SELECT Number, Row_Number() OVER (ORDER BY ID) AS RowNumber " & _
" FROM NoTable) AS Results " & _
" WHERE Results.RowNumber = " & formNumber.ToString()
command = New SqlCommand(query, con)
con.Open()
Dim datareader As SqlDataReader = cmd.ExecuteReader()
Label1.Text = datareader.GetValue(0)
datareader.Close()
See https://msdn.microsoft.com/en-us/library/ms186734.aspx

GetValue(1) does not exist, as this would refer to a second column in the select statement. You are only asking for [Number] which would be datareader.GetValue(0)

Related

All Listview data show in textbox using loop

Dim Mysqlconn = New SqlConnection
Mysqlconn.ConnectionString = "Data Source=DESKTOP-D32ONKB;Initial Catalog=Attendance;Integrated Security=True"
Dim dt As DataTable = New DataTable("studentdata")
Mysqlconn.Open()
Dim query As String
query = "select ID from studentdata where Class='" & ComboBox1.Text & "'"
Dim Command = New SqlCommand(query, Mysqlconn)
Dim dr = Command.ExecuteReader(CommandBehavior.CloseConnection)
ListView1.Items.Clear()
Dim x As ListViewItem
Do While dr.Read = True
x = New ListViewItem(dr("ID").ToString)
ListView1.Items.Add(x)
Loop
For i = 0 To ListView1.Items.Count - 1
TextBox1.Text = ListView1.Items(i).SubItems(0).Text
Next
In this code, Textbox1 is showing the last row from Listview1. My requirement is all the Listview1 data show in textbox1 one after one from Listview1. Is this possible to show in textbox1 read all data from Listview1 using loop. Thank you...
A textbox only holds one string at a time. If it's set to allow multiline strings (not clear in the question) you can separate each item with a linebreak. Otherwise you can separate the strings using a delimiter like a comma.
Dim query As String = "select ID from studentdata where Class= #class"
Using conn As New SqlConnection("Data Source=DESKTOP-D32ONKB;Initial Catalog=Attendance;Integrated Security=True"), _
cmd As New SqlCommand(query, conn)
cmd.Parameters.Add("#class", SqlDbType.NVarChar, 20).Value = ComboBox1.Text
conn.Open()
Using dr As SqlDataReader = cmd.ExecuteReader()
While dr.Read()
ListView1.Items.Add(New ListViewItems(dr("ID").ToString()))
End While
End Using
End Using
TextBox1.Text = String.Join(",", ListView1.Items.Select(Function(i) i.SubItems(0).Text))
Also note how I used a query parameter to include the combobox value in the SQL command. That's a big deal; anything else will give you trouble, usually sooner than later.
Using as loop, the proper way would be like so:
Dim lines As New List(Of String)
For i = 0 To ListView1.Items.Count - 1
lines.Add(ListView1.Items(i).Text)
Next
TextBox1.Lines = lines.ToArray()
You can't keep setting the Text property to a new value and expect the old value to hang around for no reason. You could append to the Text each time, but that is inefficient. The proper way is to create a list of the values, convert that to a String array and then assign that to the Lines property.
Note that there is no point getting the Text of the first subitem because that is the same as the Text of the item.

Query Timeout Expired when updating SQL Server from VB,NET

I'm updating SQL Server from VB.NET and keep getting the 'Query Timeout Error', I have lot's of sub routines that I run in sequence that look like the following:
Public Shared Sub Update_DailyRatings()
Dim stallStats As String = ""
Dim win As Integer = 0
Dim mSplit As Array
Dim cn As OleDbConnection = New OleDbConnection(MainForm.connectStringPublic)
cn.Open()
Dim selectString As String = "Select * FROM DailyRatings"
Dim cmd As OleDbCommand = New OleDbCommand(selectString, cn)
Dim reader As OleDbDataReader = cmd.ExecuteReader()
While (reader.Read())
stallStats = Get_Stall_Stats(reader("Track").ToString, CInt(reader("Stall")), CDbl(reader("Distance")))
If stallStats = "" Then
MainForm.NonQuery("UPDATE DailyRatings SET StallWin = 999 WHERE Horse = '" & reader("Horse").ToString & "'")
Else
mSplit = Split(stallStats, ",")
win = mSplit(0)
MainForm.NonQuery("UPDATE DailyRatings SET StallWin = " & win & " WHERE Horse = '" & reader("Horse").ToString & "'")
End If
End While
reader.Close()
cn.Close()
End Sub
The NonQuery sub looks like this:
Public Sub NonQuery(ByVal SQL As String)
Dim query As String = SQL
Try
Dim cn3 As OleDbConnection = New OleDbConnection(connectStringPublic)
cn3.Open()
Dim cmd As OleDbCommand = New OleDbCommand(query, cn3)
cmd.CommandTimeout = 90
cmd.ExecuteNonQuery()
cn3.Close()
cn3.Dispose()
cmd.Dispose()
OleDbConnection.ReleaseObjectPool()
Catch e As System.Exception
Clipboard.SetText(query)
MsgBox(e.Message)
Finally
End Try
End Sub
As you can see I've been trying ideas to fix this that I found in other threads such as extending the timeout and using the Dispose() and ReleaseObjectPool() methods but it hasn't worked, I still get query timeout error at least once when running all my subs in sequence, it's not always the same sub either.
I recently migrated from Access, this never used to happen with Access.
If you are dealing with Sql Server why are you using OleDb? I guessed that is was really access.
While your DataReader is open, your connection remains open. With the amount of processing you have going on, it is no wonder that your connection is timing out.
To begin, connections and several other database objects need to be not only closed but disposed. They may contain unmanaged resources which are released in the .Dispose method. If you are using an object that exposes a .Dispose method use Using...End Using blocks. This will take care of this problem even if there is an error.
Actually you have 2 distinct operations going on. First you are retrieving DailyRatings and then you are updating DailyRatings base on the data retrieved. So we fill a Datatable with the first chunk of data and pass it off to the second operation. Our first connection is closed and disposed.
In operation 2 we create our connection and command objects just as before except now our command has parameters. The pattern of the command is identical for every .Execute, only the values of the parameters change. This pattern allows the database, at least in Sql Sever, to cache a plan for the query and improve performance.
Public Shared Function GetDailyRatings() As DataTable
Dim dt As New DataTable
Using cn As New OleDbConnection(MainForm.connectStringPublic),
cmd As New OleDbCommand("Select * FROM DailyRatings", cn)
cn.Open()
dt.Load(cmd.ExecuteReader)
End Using
Return dt
End Function
Public Sub UpdateDailyRatings()
Dim dt = GetDailyRatings()
Using cn As New OleDbConnection(connectStringPublic),
cmd As New OleDbCommand("UPDATE DailyRatings SET StallWin = #Stall WHERE Horse = #Horse")
cmd.Parameters.Add("#Stall", OleDbType.Integer)
cmd.Parameters.Add("#Horse", OleDbType.VarChar)
cn.Open()
For Each row As DataRow In dt.Rows
cmd.Parameters("#Horse").Value = row("Horse").ToString
Dim stallStats As String = Get_Stall_Stats(row("Track").ToString, CInt(row("Stall")), CDbl(row("Distance")))
If stallStats = "" Then
cmd.Parameters("#Stall").Value = 999
Else
cmd.Parameters("#Stall").Value = CInt(stallStats.Split(","c)(0))
End If
cmd.ExecuteNonQuery()
Next
End Using
End Sub
Private Function GetStallStats(Track As String, Stall As Integer, Distance As Double) As String
Dim s As String
'Your code here
Return s
End Function
Note: OleDb does not pay attention to parameters names. It is the order that they appear in the query statement must match the order that they are added to the Parameters collection.
It's possible that OleDbDataReader is locking your table or connection as it get the data with busy connection. You can store the data in a DataTable by using OleDbDataAdapter and loop through it to run your updates. Below is the snippet how your code would look like:
Dim cmd As OleDbCommand = New OleDbCommand(selectString, cn)
Dim adapter As OleDbDataAdapter = New OleDbDataAdapter(cmd)
Dim dt As New DataTable()
adapter.Fill(dt)
For Each reader As DataRow In dt.Rows
stallStats = Get_Stall_Stats(reader("Track").ToString, CInt(reader("Stall")), CDbl(reader("Distance")))
If stallStats = "" Then
MainForm.NonQuery("UPDATE DailyRatings SET StallWin = 999 WHERE Horse = '" & reader("Horse").ToString & "'")
Else
mSplit = Split(stallStats, ",")
win = mSplit(0)
MainForm.NonQuery("UPDATE DailyRatings SET StallWin = " & win & " WHERE Horse = '" & reader("Horse").ToString & "'")
End If
Next
cn.Close()

Cannot insert value NULL into column 'intGolferEventYearID', table does not allow nulls

I have a dialog with a combobox listing the years an event was held.
Changing the year, changes the following list boxes
One list box 'called inEvent' shows all golfers the attended said event.
The other list box called 'available' that shows every golfer we have in our database that did not attend that years event
It has two buttons. One removes golfers from 'inEvent' and moves them to 'available'. This button works.
The other button does the opposite. It adds available golfers to the selected event year. But it gives me the error -
"The statement has been terminated. Cannot insert the value NULL into column 'intGolferEventYearID', table 'dbo.TGolferEventYears'; column does not allow nulls. INSERT fails."
Changing any line of code in VB results in a different error. So I think the error has to come from SQL itself which I don't know much about. Only other thing I can think of is the listbox is giving the wrong information.
Private Sub btnAddAuto_Click(sender As Object, e As EventArgs) Handles btnAddAuto.Click
Dim strInsert As String = ""
Dim cmdInsert As OleDb.OleDbCommand ' used for our Select statement
Dim dt As DataTable = New DataTable ' table we will load from our reader
Dim intRowsAffected As Integer
' open the DB
OpenDatabaseConnectionSQLServer()
' Build the select statement
strInsert = "INSERT INTO TGolferEventYears ( intGolferID, intEventYearID) Values (" & lstAvailable.SelectedValue & ", " & cboEvents.SelectedIndex + 1 & ")"
' Retrieve all the records
cmdInsert = New OleDb.OleDbCommand(strInsert, m_conAdministrator)
intRowsAffected = cmdInsert.ExecuteNonQuery()
' close the database connection and reload the form so the changes are shown
CloseDatabaseConnection()
frmEventsGolfers_Load(sender, e)
End Sub
I separated the data access code from the user interface. This will make it easy to remove data access entirely from the Form if you later desire.
Private Sub MoveGolfer(GolfID As Integer, YearID As Integer)
'If you keep your connections local you can be sure they are
'closed and disposed which is what the Using...End Using blocks do.
Using cn As New SqlConnection("Your connection string")
Using cmd As New SqlCommand("INSERT INTO TGolferEventYears ( intGolferID, intEventYearID) Values (#Golf, #Year;")
'Always use parameters to protect against Sql injection
cmd.Parameters.Add("#Golf", SqlDbType.Int).Value = GolfID
cmd.Parameters.Add("#Year", SqlDbType.Int).Value = YearID
cn.Open()
cmd.ExecuteNonQuery()
End Using
End Using
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim GolferID As Integer = CInt(lstAvailable.SelectedValue)
Dim Year As Integer = cboEvents.SelectedIndex + 1
Try
MoveGolfer(GolferID, Year)
Catch ex As Exception
'Catch a more specific exception and handle accordingly
MessageBox.Show(ex.Message)
End Try
End Sub
Since I don't really understand SQL I didn't realize my PK didn't have the IDENTITY tag added in the table. Adding this fixed my issue.
Here is the code I added
Dim strSelect As String
Dim cmdSelect As OleDb.OleDbCommand
Dim drSourceTable As OleDb.OleDbDataReader
Dim intNextHighestRecordID As
strSelect = "SELECT MAX(intDealerAutos) + 1 AS intNextHighestRecordID " &
" FROM TDealerAutos"
'Excute command
cmdSelect = New OleDb.OleDbCommand(strSelect, m_conAdministrator)
drSourceTable = cmdSelect.ExecuteReader
'Read result( highest ID )
drSourceTable.Read()
'Null? (Empty Table)
If drSourceTable.IsDBNull(0) = True Then
'Yes, start numbering at 1
intNextHighestRecordID = 1
Else
'No, get the next highest ID
intNextHighestRecordID = CInt(drSourceTable.Item(0))
End If
'Build the select statement
strInsert = "INSERT INTO TDealerAutos ( intDealerAutos, intDealerID, intAutoID)" &
"Values (" & intNextHighestRecordID & ", " & cboDealers.SelectedValue & ", " & lstAvailable.SelectedValue & ")"

how to get each unique value from access database column and add to combobox items

I am not professional but i am trying to learn VB.net. I am making a project where i am stuck where i want to get each unique value from a column in access database and add it to my combobox. Can anybody help me ??
Private Sub showItems()
Dim comm As OleDbCommand
Dim commStr As String = "SELECT Item_Name FROM Add_Items WHERE (Item_Name <> '"
Dim RD As OleDbDataReader
conn = New OleDbConnection(connStr)
conn.Open()
If cbItemname.Items.Count = 0 Then
comm = New OleDbCommand("Select Item_Name from Add_Items", conn)
RD = comm.ExecuteReader
While RD.Read
cbItemname.Items.Add(RD.GetString(0))
End While
End If
For Each i As Object In cbItemname.Items
comm = New OleDbCommand(commStr & i & "')", conn)
RD = comm.ExecuteReader
While RD.Read
cbItemname.Items.Add(RD.GetString(0))
Exit While
End While
Next
conn.Close()
End Sub
comm = New OleDbCommand("Select DISTINCT Item_Name from Add_Items", conn)
http://office.microsoft.com/en-in/access-help/HV080760568.aspx
You can get this error because your database table name is incorrect. Make sure you are in the Tables tab and check the name of the table. DISTINCT and UNIQUE(for MySQL) is correct solution for this.
I followed instructions given by vipul. It was working nicely and i made some more private subs for brands and Models and it suddenly stopped working. Now, when my form loads from previous parent form it hangs.
Private Sub showItems()
Dim comm As OleDbCommand
Dim commStr As String = "SELECT DISTINCT Item_Name from Add_Items"
Dim ReadData As OleDbDataReader
itemnamecombo.Items.Clear()
ItemChkboxList.Items.Clear()
Try
conn = New OleDbConnection(ConnStr)
conn.Open()
comm = New OleDbCommand(commStr, conn)
ReadData = comm.ExecuteReader
While ReadData.Read
itemnamecombo.Items.Add(ReadData.GetString(0))
ItemChkboxList.Items.Add(ReadData.GetString(0))
End While
Catch ex As Exception
'MessageBox.Show(ex.Message)
Finally
conn.Dispose()
End Try
If itemnamecombo.Items.Count <> 0 Then
itemnamecombo.SelectedIndex = 0
End If
End Sub

Compare values in DGV column with database values and add value to new DGV column

So, Access database has two columns 1st is seller name (SELLER) and second is it's code (CODE). Access database is database with all SELLER CODEs.
DGV is populated from other source and consists of some of CODEs from Access database.
DGV has one column with codes.
I would like to create and populate new column (SELLERNAME) in DGV with SELLER names based on DGV codes and Access database CODEs.
I am going to give an example since it's hard for me to explain this better :
DGV : Column 0, 1st value = 0055, in Access database code 0055 corresponds to the name John
so I would like to put name "John" in DGV Column1, 1st value, nest to "0055" and so on
Here is my code so far :
DataGridView1.Columns.Add("SELLERNAME", "SELLERNAME") '1
Dim cn As OleDb.OleDbConnection
Dim cmd As OleDb.OleDbCommand
Dim odr As OleDb.OleDbDataReader
Dim strSQL As String
cn = New OleDb.OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=w:\SCodes.MDB")
strSQL = "SELECT SELLER, CODE FROM SCBASE"
cn.Open()
cmd = New OleDb.OleDbCommand(strSQL, cn)
odr = cmd.ExecuteReader(CommandBehavior.CloseConnection)
Do While odr.Read
For i As Integer = 0 To DataGridView1.Rows.Count - 1
DataGridView1.Rows(i).Cells(1).Value = odr.GetValue(1).ToString()
Next
Loop
I don't know what to do next after line For i As Integer = 0 To DataGridView1.Rows.Count - 1.
EDIT :
I think I am close but I need help with one line of code :
Using sqlconn = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=w:\SCodes.mdb")
Using sqlcmd = New OleDbCommand("Select SELLER, CODE From SCBASE Where CODE = #CODE ", sqlconn)
sqlcmd.Parameters.AddWithValue("#CODE ", DataGridView1.Rows(i).Cells(0).Value) 'HOW TO ADD THIS LINE IN LOOP BELOW
sqlconn.Open()
Dim result = sqlcmd.ExecuteReader()
Do While (result.Read())
For i As Integer = 0 To DataGridView1.Rows.Count - 1
DataGridView1.Rows(i).Cells(1).Value = (result("DOBAVLJAC"))
Next
Loop
End Using
End Using
I had no success with a trial and error. I am trying to put this line sqlcmd.Parameters.AddWithValue("#CODE ", DataGridView1.Rows(i).Cells(0).Value) in loop below but I am getting all sorts of error.
Yes, you are very close. You just need to .Add the Parameter outside the loop and then set its .Value inside the loop like this
Using sqlconn = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=w:\SCodes.mdb")
sqlconn.Open()
Using sqlcmd = New OleDbCommand("Select SELLER, CODE From SCBASE Where CODE = ?", sqlconn)
sqlcmd.Parameters.Add("?", OleDbType.VarWChar, 255)
sqlcmd.Prepare()
For i As Integer = 0 To DataGridView1.Rows.Count - 1
sqlcmd.Parameters(0).Value = DataGridView1.Rows(i).Cells(0).Value
Using result = sqlcmd.ExecuteReader()
If result.Read() Then
DataGridView1.Rows(i).Cells(1).Value = result("SELLER")
End If
End Using
Next
End Using
End Using

Resources