System.IndexOutOfRangeException: while inserting data to mdf database file - vb.net

Im getting this error while inserting data to my mdf database file
System.IndexOutOfRangeException: 'An SqlParameter with ParameterName '#qtysold' is not contained by this SqlParameterCollection.'
This is my code for order function
Function order(ByVal cart As List(Of Integer), ByVal product_qty As List(Of Integer))
If con.State = ConnectionState.Open Then
con.Close()
End If
con.Open()
'INSERT INTO PRODUCT TABLE
cmd.CommandType = CommandType.Text
cmd.CommandText = "UPDATE product SET product_qty= product_qty - #qty WHERE product_id= #id"
cmd.Parameters.Add("#qty", SqlDbType.Int)
cmd.Parameters.Add("#id", SqlDbType.Int)
For i As Integer = 0 To cart.Count - 1
cmd.Parameters("#id").Value = cart(i)
cmd.Parameters("#qty").Value = product_qty(i)
cmd.ExecuteNonQuery()
Next
'INSERT INTO SALES TABLE
cmd.CommandType = CommandType.Text
cmd.CommandText = "INSERT INTO sales VALUES (#id, #productname, #qtysold, #date)"
cmd.Parameters.Add("#id", SqlDbType.Int)
cmd.Parameters.Add("#productname", SqlDbType.VarChar)
cmd.Parameters.Add("#qtysold", SqlDbType.Int)
cmd.Parameters.Add("#date", SqlDbType.Date)
For i As Integer = 0 To cart.Count - 1
cmd.Parameters("#id").Value = cart(i)
cmd.Parameters("#productname").Value = getName(cart(i))
cmd.Parameters("#qtysold").Value = product_qty(i)
cmd.Parameters("#date").Value = datefield.Text
cmd.ExecuteNonQuery()
Next
cart.Clear()
product_qty.Clear()
refresh()
End Function
THE ERROR HAPPENS HERE
cmd.Parameters("#qtysold").Value = product_qty(i)

That seems an odd exception in that situation as the code looks OK to me but it's wrong even if it did work. Don't add the parameters and then get them back by name over and over. The Add method you're calling returns the SqlParameter object added so assign it to a variable and then use that:
Dim idParameter = cmd.Parameters.Add("#id", SqlDbType.Int)
Dim productionNameParameter = cmd.Parameters.Add("#productname", SqlDbType.VarChar)
Dim qtySoldParameter = cmd.Parameters.Add("#qtysold", SqlDbType.Int)
Dim dateParameter = cmd.Parameters.Add("#date", SqlDbType.Date)
For i As Integer = 0 To cart.Count - 1
idParameter.Value = cart(i)
productionNameParameter.Value = getName(cart(i))
qtySoldParameter.Value = product_qty(i)
dateParameter.Value = datefield.Text
cmd.ExecuteNonQuery()
Next
NEVER use the same complex expression over and over. ALWAYS use it once and assign the result to a variable, then use that variable over and over. In this case, you don't even have to use the complex expression once, because you already had the object but just ignored it.

Related

SQL Error Regarding apostrophe from datagridview using parameter in query

Dim sc = datagridview.rows(0).cells(0).value
cmd = New SqlCommand("insert into Schedule (Name) values(#sc)", con)
with cmd
.Connection = con
.CommandType = CommandType.Text
.Parameters.AddWithValue("#sc", sc.cells(0))
end with
The value from the datagrid view contains an apostrophe where I get an error in ('s). Any work around with this?
EDIT:
This is the error:
SqlException was unhandled. Incorrect syntax near 's'.
EDIT 2: i've revised the code to this:
for 1=0 to datagridview.rows.count -1
Dim tname = datagridview.Rows(i)
cmd = New SqlCommand("insert into Schedule (Name) values(#sc)", con)
with cmd
.Connection = con
.CommandType = CommandType.Text
.Parameters.AddWithValue("#sc", sc.cells(0).value)
end with
con.Close()
con.Open()
If Not cmd.ExecuteNonQuery() > 0 Then
con.Close()
Exit For
End If
next
Error is still the same.
As it goes through all the values quickly in one go, I would make the connection once and change the value of the parameter for each iteration, like this:
Dim sql = "INSERT INTO [Schedule] ([Name]) VALUES(#sc)"
Using conn As New SqlConnection("your connection string"),
cmd As New SqlCommand(sql, conn)
cmd.Parameters.Add(New SqlParameter With {.ParameterName = "#sc",
.SqlDbType = SqlDbType.NVarChar,
.Size = -1})
conn.Open()
For i = 0 To dgv.Rows.Count - 1
Dim tname = dgv.Rows(i).Cells(0).Value.ToString()
cmd.Parameters("#sc").Value = tname
cmd.ExecuteNonQuery()
Next
End Using
Including the size of the parameter in its declaration helps SQL Server keep things tidy (it only needs one entry in the query cache).
The Using statement makes sure that the connection and command are disposed of properly when they are finished with.
The purpose of checking If Not cmd.ExecuteNonQuery() > 0 was not clear to me, so I didn't put that in.
(I used "dgv" as the name of the DataGridView.)
Try to replace the " ' " by " '' "
Dim sc = datagridview.rows(0).cells(0).value
cmd = New SqlCommand("insert into Schedule (Name) values(#sc)", con)
with cmd
.Connection = con
.CommandType = CommandType.Text
.Parameters.AddWithValue("#sc", replace(sc.cells(0), "'", "''")
end with
/**** EDIT ****/
I will consider by the way that your code have a problem with the affectation of the value. You get the value into SC then try to get again the value from cell
Dim sc = datagridview.rows(0).cells(0).value
cmd = New SqlCommand("insert into Schedule (Name) values(#sc)", con)
with cmd
.Connection = con
.CommandType = CommandType.Text
.Parameters("#sc").value = sc.replace("'", "''")
end with

Failed to convert parameter value from a string to int32

cmd1.CommandText = "insert into tblInvoiceDetails (InvoiceNo)values(#InvoiceNo )"
With cmd1.Parameters
.AddWithValue("#InvoiceNo", NumericUpDown1.Value)
cmd1.CommandText = "insert into tblInvoiceDetails (itemno,ItemName,Qt,Price,Total)values(#itemno,#ItemName,#Qt,#Price,#Total)"
'cmd1.Parameters.Add("#InvoiceNo", NumericUpDown1 .Value )
cmd1.Parameters.Add("#itemno", SqlDbType.Int)
cmd1.Parameters.Add("#ItemName", SqlDbType.VarChar)
cmd1.Parameters.Add("#Qt", SqlDbType.Int)
cmd1.Parameters.Add("#Price", SqlDbType.Money)
cmd1.Parameters.Add("#Total", SqlDbType.Money)
For x As Integer = 0 To DataGridView2.RowCount - 1
cmd1.Parameters(0).Value = DataGridView2.Rows(x).Cells(0).Value
cmd1.Parameters(1).Value = DataGridView2.Rows(x).Cells(1).Value
cmd1.Parameters(2).Value = DataGridView2.Rows(x).Cells(2).Value
cmd1.Parameters(3).Value = DataGridView2.Rows(x).Cells(3).Value
cmd1.Parameters(4).Value = DataGridView2.Rows(x).Cells(4).Value
Next
End With
cmd1.ExecuteNonQuery()
cmd1.Parameters.Clear()
It looks like you are inserting several values from a DataGridView into the database, and they all have the same InvoiceNo.
To make it easier to see which parameter is which, you can refer to them by the parameter name.
To make sure that the data types are correct, use the various Convert functions.
You would need to execute the query for each row of data. There is no need to clear the parameters, just change the value of each one.
So your code would end up something like:
Dim sql = "INSERT INTO tblInvoiceDetails ([itemno], [ItemName], [Qt], [Price], [Total]) VALUES (#itemno, #ItemName, #Qt, #Price, #Total)"
Using conn As New SqlConnection("your connection string"),
cmd1 As New SqlCommand(sql, conn)
cmd1.Parameters.Add("#InvoiceNo", SqlDbType.Int)
cmd1.Parameters.Add("#itemno", SqlDbType.Int)
'TODO: Use the correct size for the VARCHAR column:
cmd1.Parameters.Add("#ItemName", SqlDbType.VarChar, 128)
cmd1.Parameters.Add("#Qt", SqlDbType.Int)
cmd1.Parameters.Add("#Price", SqlDbType.Money)
cmd1.Parameters.Add("#Total", SqlDbType.Money)
cmd1.Parameters("#InvoiceNo").Value = Convert.ToInt32(NumericUpDown1.Value)
conn.Open()
For x As Integer = 0 To DataGridView2.RowCount - 1
cmd1.Parameters("#itemno").Value = Convert.ToInt32(DataGridView2.Rows(x).Cells(0).Value)
cmd1.Parameters("#ItemName").Value = Convert.ToString(DataGridView2.Rows(x).Cells(1).Value)
cmd1.Parameters("#Qt").Value = Convert.ToInt32(DataGridView2.Rows(x).Cells(2).Value)
cmd1.Parameters("#Price").Value = Convert.ToDecimal(DataGridView2.Rows(x).Cells(3).Value)
cmd1.Parameters("#Total").Value = Convert.ToDecimal(DataGridView2.Rows(x).Cells(4).Value)
cmd1.ExecuteNonQuery()
Next
End Using
The Using Statement takes care of cleaning up unmanaged resources used by the SqlConnection and SqlCommand.
When you have a string parameter (#ItemName in this case), it is best to tell it the size of the column in the database. I guessed at 128, but you should put in the actual value.
Also, you really should give the controls meaningful names, for example "InvoiceNoSelector" instead of "NumericUpDown1".

Update table in sql database from listview items

Hello folks am trying read from the table identify a specific column if not YES then update my table using items from listview
Public Sub FeesFromSetFees(lst As ListView, Amt As String, Year As String, Clss As String, Term As String, Mode As String)
Dim txtID As New TextBox
Dim txtbal As New TextBox
Dim toText As New TextBox
Dim add As New TextBox
Try
con = New SqlConnection(My.Settings.DeseretConnectionString)
con.Open()
sql = "SELECT * FROM Fees"
command = New SqlCommand(sql, con)
reader = command.ExecuteReader
While reader.Read()
toText.Text = reader.Item("scholarship").ToString
If toText.Text.ToUpper <> "YES" Then
txtID.Text = reader.Item("id").ToString
add.Text = reader.Item("balance").ToString
txtbal.Text = CType(Amt.Trim, Double) + CType(add.Text.Trim, Double)
Dim item As New ListViewItem(txtbal.Text)
item.SubItems.Add(txtID.Text)
lst.Items.Add(item)
Dim lstId As New List(Of String)
Dim lstBalance As New List(Of String)
For Each li As ListViewItem In lst.Items
lstId.Add(li.SubItems(0).ToString)
lstBalance.Add(li.SubItems(1).ToString)
Next
Dim Sql = "Update fees Set class = #Class, year = #Year, mode = #Mode,term = #Term, balance = #Balance where id = #ID"
Using cn As New SqlConnection(My.Settings.DeseretConnectionString)
Using cmd As New SqlCommand(Sql, cn)
With cmd.Parameters
.Add("#Class", SqlDbType.VarChar).Value = Clss
.Add("#Year", SqlDbType.VarChar).Value = Year
.Add("#Mode", SqlDbType.VarChar).Value = Mode
.Add("#Term", SqlDbType.VarChar).Value = Term
.Add("#Balance", SqlDbType.VarChar)
.Add("#ID", SqlDbType.VarChar)
End With
cn.Open()
For index = 0 To lstId.Count - 1
cmd.Parameters("#Balance").Value = lstBalance(index)
cmd.Parameters("#ID").Value = lstId(index)
cmd.ExecuteNonQuery()
Next
End Using
End Using
MessageBox.Show("successful")
End If
End While
con.Close()
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
End Sub
I get my successful message but nothing really happen to data in the table
Public Sub FeesFromSetFees(Amt As String, Year As String, Clss As String, Term As String, Mode As String)
Dim txtID As New TextBox
Dim txtbal As New TextBox
Dim toText As New TextBox
Dim add As New TextBox
Try
con = New SqlConnection(My.Settings.DeseretConnectionString)
con.Open()
sql = "SELECT * FROM Fees"
command = New SqlCommand(sql, con)
reader = command.ExecuteReader
While reader.Read()
toText.Text = reader.Item("scholarship").ToString
If toText.Text.ToUpper <> "YES" Then
txtID.Text = reader.Item("id").ToString
add.Text = reader.Item("balance").ToString
txtbal.Text = CType(Amt.Trim, Double) + CType(add.Text.Trim, Double)
Dim Sql = "Update fees Set class = #Class, year = #Year, mode = #Mode,term = #Term, balance = #Balance where id = #ID"
Using cn As New SqlConnection(My.Settings.DeseretConnectionString)
Using cmd As New SqlCommand(Sql, cn)
With cmd.Parameters
.Add("#Class", SqlDbType.VarChar).Value = Clss
.Add("#Year", SqlDbType.VarChar).Value = Year
.Add("#Mode", SqlDbType.VarChar).Value = Mode
.Add("#Term", SqlDbType.VarChar).Value = Term
.Add("#Balance", SqlDbType.VarChar).Value = txtbal.Text
.Add("#ID", SqlDbType.VarChar).Value = txtID.Text
cn.Open()
cmd.ExecuteNonQuery()
End With
End Using
End Using
MessageBox.Show("successful")
End If
End While
con.Close()
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
End Sub

How to convert SqlDbType datetime to string in VB

I want to display the date column into a textbox that a stored procedure returns. The error displays the column name.
Thank you for your help!
SQL stored procedure:
SELECT MAX(NrTimesUpdated) AS NrTimesUpdated,
CONVERT(varchar(20),MAX(DateModified),101) AS DateEntered
FROM Credentials
WHERE ID = #ID
END
VB code:
Dim cmd As New SqlClient.SqlCommand
cmd = New SqlCommand("get_credentials", cn)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add("#ID", SqlDbType.Int).Value = lblID.Text
Dim rdr = cmd.ExecuteReader
If rdr.Read Then
lblDate.Text = rdr("DateEntered").ToString().Trim()
End If
rdr.Close()

Insert and Select at the same time in a stored procedure

I have the following stored procedure:
create procedure Insert_Maintenance
(
#PlateNo nvarchar(10),
#MaintenanceType nvarchar(150),
#Name nvarchar(300),
#MaintenanceDate date,
#Qty int,
#IndivisualVal float,
#TotalVal float,
#Notes nvarchar(300)
)
as
insert into Maintenance(MaintenanceNo, PlateNo, MaintenanceType, AutoCenterNo,MaintenanceDate, Qty, IndivisualVal, TotalVal, Notes)
values ((1+(select Max(MaintenanceNo) from Maintenance)), #PlateNo, #MaintenanceType, (select AutoCenterNo from AutoCenter where Name = #Name), #MaintenanceDate, #Qty, #IndivisualVal, #TotalVal, #Notes)
Select Max(MaintenanceNo) AS MNo from Maintenance
A user will insert new maintenance operation via VB.NET interface. The information of the maintenance will be inserted into the database. The ID of the maintenance will increase by 1; as it is shown in the code. Since this is the case, after inserting the information I want to show a message that tells the user that information entered correctly and the ID of this operation is the value of MNo.
Basically, the problem is not with the VB.NET code because the message works fine but the problem is related to the select statement that shows the maintenance ID to the user.
The code in VB.NET
Dim ConnectString As String
ConnectString = ""
Dim connection As New SqlConnection(ConnectString)
'Dim parm1 As SqlParameter
'parm1 = New SqlParameter("#MaintenanceNo", SqlDbType.Int)
'parm1.Value = MaintenanceNoTextBox.Text
Dim parm2 As SqlParameter
parm2 = New SqlParameter("#PlateNo", SqlDbType.NVarChar)
parm2.Value = PlateNoComboBox.Text
Dim parm3 As SqlParameter
parm3 = New SqlParameter("#MaintenanceType", SqlDbType.NVarChar)
parm3.Value = MaintenanceTypeTextBox.Text
Dim parm4 As SqlParameter
parm4 = New SqlParameter("#Name", SqlDbType.NVarChar)
parm4.Value = NameComboBox.Text
Dim parm5 As SqlParameter
parm5 = New SqlParameter("#MaintenanceDate", SqlDbType.Date)
parm5.Value = MaintenanceDateDateTimePicker.Value
Dim parm6 As SqlParameter
parm6 = New SqlParameter("#Qty", SqlDbType.Int)
parm6.Value = QtyTextBox.Text
Dim parm7 As SqlParameter
parm7 = New SqlParameter("#IndivisualVal", SqlDbType.Float)
parm7.Value = IndivisualValTextBox.Text
Dim parm8 As SqlParameter
parm8 = New SqlParameter("#TotalVal", SqlDbType.Float)
parm8.Value = TotalValTextBox.Text
Dim parm9 As SqlParameter
parm9 = New SqlParameter("#Notes", SqlDbType.NVarChar)
parm9.Value = NotesTextBox.Text
Dim cmd As SqlCommand = New SqlCommand()
cmd.Connection = connection
cmd.CommandType = CommandType.StoredProcedure
cmd.CommandText = "Insert_Maintenance"
'cmd.Parameters.Add(parm1)
cmd.Parameters.Add(parm2)
cmd.Parameters.Add(parm3)
cmd.Parameters.Add(parm4)
cmd.Parameters.Add(parm5)
cmd.Parameters.Add(parm6)
cmd.Parameters.Add(parm7)
cmd.Parameters.Add(parm8)
cmd.Parameters.Add(parm9)
Try
connection.Open()
cmd.ExecuteNonQuery()
Dim dreader As SqlDataReader
dreader = cmd.ExecuteReader()
Dim a As String
a = dreader("MNo").ToString
MessageBox.Show("Information entered, ID is " + a)
dreader.Close()
'MaintenanceNoTextBox.Text = ""
PlateNoComboBox.Text = ""
MaintenanceTypeTextBox.Text = ""
NameComboBox.Text = ""
'MaintenanceDateDateTimePicker.Value = ""
QtyTextBox.Text = ""
IndivisualValTextBox.Text = ""
TotalValTextBox.Text = ""
NotesTextBox.Text = ""
Catch ex As Exception
MessageBox.Show("Something wrong (" + ex.Message + ")")
Finally
connection.Close()
End Try
Any suggestions guys !! Thanks
To solve your problem you need to just change one line and remove a bunch of unnecessary code
Dim cmd As SqlCommand = New SqlCommand()
cmd.Connection = connection cmd.CommandType = CommandType.StoredProcedure
cmd.CommandText = "Insert_Maintenance"
.... you need to build the parameters collection here .....
Try
connection.Open()
Dim result = cmd.ExecuteScalar() ' <- Instead of ExecuteNonQuery '
if result IsNot Nothing Then
Console.WriteLine("The Mno is:" & Convert.ToInt32(result)
End If
ExecuteScalar returns the first column of the first row in your results. This should resolve the VB.NET side of your code. Of course, if you don't need to control the values inserted in the column MaintenanceNo then the next action to take is to set the Identity property to Yes in the field properties. In this way you could remove the last lines of your storedprocedure and forget to pass anything for the MaintenaceNo field
INSERT INTO Maintenance(PlateNo, MaintenanceType, AutoCenterNo,MaintenanceDate, Qty,
IndivisualVal, TotalVal, Notes)
VALUES (#PlateNo, #MaintenanceType,
(select AutoCenterNo from AutoCenter where Name = #Name),
#MaintenanceDate, #Qty, #IndivisualVal, #TotalVal, #Notes)
SELECT SCOPE_IDENTITY()
I think ID of Maintainance table should be auto-increment. For achieving that you can set Is Identity to Yes
In the end of insert if you want the ID than you can get by
Select SCOPE_IDENTITY()
If you want to increment ID manually then try this :
declare #newid int
Select #newid = Max(ISNULL(MaintenanceNo, 0)) from Maintenance
set #newid = #newid + 1
then use #newid for insert and in the end Select #newid