VB.Net freezing when adding 10000+ rows to SQL from list - sql

I am running a RESTful API service which gets data from a server as a JSON string. Around 20000 rows are being selected.
Dim js As New JavaScriptSerializer()
Dim prodlist As List(Of Product) = js.Deserialize(Of List(Of Product))(JSONreturn)
The 20000 rows are populated in the list prodlist. Checked the count and manually verified the list.
I need to insert these rows in a client machine. However, while inserting the rows, it freezes or stops after inserting around 600-700 rows. Below is the code I am using for inserting.
For Each item As Product In prodlist
Dim SPName As String = "someSPname"
With connectionstring
.Clear()
.Parameters("#itemnumber", SqlDbType.VarChar, ParameterDirection.Input, , item.itemnumber
.Parameters("#itemtype", SqlDbType.VarChar, ParameterDirection.Input, , item.itemtype)
.Parameters("#DESCRIPTION", SqlDbType.VarChar, ParameterDirection.Input, , item.DESCRIPTION)
.Execute(SPName)
End With
Next
No error is thrown. It just freezes after inserting roughly 600-700 rows everytime.
Bulk insert is not an option. How do I resolve this?
UPDATE : Adding connection class. Pretty sure there is no issue with this :
Public Class ConnectionClass
Public ReadOnly Property ConnectionString() As String
Get
Return GetConfiguration()
End Get
End Property
Public Sub Parameters(ByVal param_name As String, ByVal type As SqlDbType, ByVal direction As ParameterDirection, Optional param_size As Int32 = Nothing, Optional param_value As Object = Nothing)
Dim sqlParam As SqlParameter = Nothing
Try
sqlParam = New SqlParameter(param_name, type)
sqlParam.Size = param_size
sqlParam.Direction = direction
sqlParam.Value = param_value
Lstparam.Add(sqlParam)
Finally
If sqlParam IsNot Nothing Then
sqlParam = Nothing
End If
End Try
End Sub
Public Sub Execute(ByVal strSpName As String, Optional ByVal Type As CommandType = CommandType.StoredProcedure)
Try
sqlcmd = New SqlCommand()
sqlcmd.Connection = connection
''Setting the timeout to 50 mins as setup in the previous application
sqlcmd.CommandTimeout = 3000
If transaction IsNot Nothing Then
sqlcmd.Transaction = transaction
End If
sqlcmd.CommandType = Type
sqlcmd.CommandText = strSpName
For Each argument As SqlParameter In Lstparam
sqlcmd.Parameters.Add(argument)
Next
For introw As Integer = 0 To sqlcmd.Parameters.Count - 1
If sqlcmd.Parameters.Item(introw).ParameterName.Contains("Parameter") Then
sqlcmd.Parameters.Item(introw).ParameterName = String.Empty
End If
Next
sqlcmd.ExecuteNonQuery()
Catch ex As Exception
Throw
End Try
End Sub
Public Sub Clear()
ClearParameters()
Lstparam.Clear()
End Sub
Public Sub ClearParameters()
If Not sqlcmd Is Nothing Then
Do Until sqlcmd.Parameters.Count = 0
sqlcmd.Parameters.Clear()
Loop
End If
End Sub
Public Function GetConfiguration() As String
Dim sbConnectionString As New StringBuilder
With sbConnectionString
.Append("Data Source=")
.Append(ServerName)
.Append(";")
.Append("Initial Catalog =")
.Append(DatabaseName)
.Append(";")
.Append("User ID =")
.Append(UserName)
.Append(";")
.Append("Password =")
.Append(UserPassword)
End With
Return sbConnectionString.ToString()
End Function
Public Function CreateClientConnection() As SqlConnection
Dim connectionString As String
Try
connectionString = GetConfiguration()
Dim substrings() As String = connectionString.ToUpper.Split(";")
Dim substrings1() As String = connection.ConnectionString.ToUpper.Split(";")
If Not (connection.State = ConnectionState.Open) Then
connection.ConnectionString = connectionString
connection.Open()
ElseIf Not (Trim(substrings(0)) = Trim(substrings1(0))) Then
If connection IsNot Nothing Then
connection.Dispose()
End If
connection.ConnectionString = connectionString
connection.Open()
End If
Return connection
Catch ex As Exception
If connection IsNot Nothing Then
connection.Dispose()
End If
Throw ex
End Try
End Function
End Class

Related

getting data from mysql database by using thread in vb.,net

I'm trying to get data from database but I got an error:
There is already an open DataReader associated with this Connection
which must be closed first
what I did is the following codes:
1: I have a module that contains the following sub:
Public Function CheckServerConn() As Boolean
Try
_ServerConnStr = New MySqlConnection(My.Settings.DbPath)
If _ServerConnStr.State = ConnectionState.Open Then
_ServerConnStr.Close()
End If
If _ServerConnStr.State = ConnectionState.Closed Then
_ServerConnStr.Open()
Return True
End If
Catch ex As Exception
MsgBox("Check The Conn " & ex.Message, Me_MsgInfoStyle, Me_MsgCaptionStr)
Return False
End Try
#Disable Warning BC42353 ' Function doesn't return a value on all code paths
End Function
2: I have this subroutine in class called "ClsMySql":
'GetData
Public Sub GetData(ByVal SqlStr As String, ByVal xDt As DataTable, ByVal xPar() As MySqlParameter)
Using xCmd As New MySqlCommand() With {
.CommandType = CommandType.Text,
.CommandText = SqlStr,
.Connection = _ServerConnStr,
.CommandTimeout = 5000000
}
If xPar IsNot Nothing Then
For i As Integer = 0 To xPar.Length - 1
xCmd.Parameters.Add(xPar(i))
Next
End If
Using xDa As New MySqlDataAdapter(xCmd)
xDa.Fill(xDt)
End Using
xDt.Dispose()
End Using
End Sub
3: I have a class for the table that have the following method:
Public Sub MySql_Get_Daf()
xClsMySql = New ClsMySql
Dim SqlStr As String = "SELECT RegID,RegType, tblregs1.`RegRef`,`RegDate`, COUNT(`RegdID`) AS xCount
,IF(COUNT(`RegdID`) =3,'Ok','Error') AS xResult FROM tblregs1
INNER JOIN tblregs2 ON tblregs2.RegRef = tblregs1.RegRef
WHERE `RegType` = 'Daf'
GROUP BY tblregs1.`RegRef`
ORDER BY COUNT(`RegdID`) ASC"
Dt_Get_Daf = New DataTable()
xClsMySql.GetData(SqlStr, Dt_Get_Daf, Nothing)
End Sub
Public Sub MySql_Get_Qbd()
xClsMySql = New ClsMySql
Dim SqlStr As String = "SELECT RegID,RegType, tblregs1.`RegRef`,`RegDate`, COUNT(`RegdID`) AS xCount
,IF(COUNT(`RegdID`) =3,'Ok','Error') AS xResult FROM tblregs1
INNER JOIN tblregs2 ON tblregs2.RegRef = tblregs1.RegRef
WHERE `RegType` = 'Qbd'
GROUP BY tblregs1.`RegRef`
ORDER BY COUNT(`RegdID`) ASC"
Dt_Get_Qbd = New DataTable()
xClsMySql.GetData(SqlStr, Dt_Get_Qbd, Nothing)
End Sub
Public Sub MySql_Get_All()
Dim xThread As Thread = New Thread(Sub() MySql_Get_Daf())
Dim xThread2 As Thread = New Thread(Sub() MySql_Get_Qbd())
xThread.Start()
xThread2.Start()
End Sub
when I call MySql_Get_All by a button it gives me the next error:
There is already an open DataReader associated with this Connection
which must be closed first
can anybody tell me what's the wrong here

OleDb.ExecuteNonQuery always returning 0

I looked into previously asked such questions but none of the solutions worked for me.
I am having trouble updating a Boolean column in my Access database. But the query works just fine in Access.
What I have already tried:
Directly using TRUE or FALSE in the SqlCommand
Using Parameters.Add() instead of Parameters.AddWithValue()
My ClickEvent:
Private Sub Update_Click(sender As Object, e As RoutedEventArgs) Handles btn_update.Click
Dim mc As New UsersModule() With {
.UserID = tbx_userid.Text,
.UserName = tbx_username.Text,
.UserPassword = tbx_password.Text,
.UserRole = combx_role.SelectedValue.ToString,
.UserFullname = tbx_fullname.Text,
.UserActive = cbx_active.IsChecked
}
Dim bridge As New UsersBridge()
If bridge.UpdateUser(mc) Then
MsgBox("User's Data Updated Successfully")
Else
MsgBox("Something went wrong :/")
End If
End Sub
My Module class:
Public Class UsersModule
Private ID As Integer, Name As String, Pass As String, Role As String, Fullname As String, isActive As Boolean
Public Property UserID() As Integer
Get
Return ID
End Get
Protected Friend Set(value As Integer)
ID = value
End Set
End Property
Public Property UserName() As String
Get
Return Name
End Get
Protected Friend Set(value As String)
Name = value
End Set
End Property
Public Property UserPassword() As String
Get
Return Pass
End Get
Protected Friend Set(value As String)
Pass = value
End Set
End Property
Public Property UserRole() As String
Get
Return Role
End Get
Protected Friend Set(value As String)
Role = value
End Set
End Property
Public Property UserFullname() As String
Get
Return Fullname
End Get
Protected Friend Set(value As String)
Fullname = value
End Set
End Property
Public Property UserActive() As Boolean
Get
Return isActive
End Get
Protected Friend Set(value As Boolean)
isActive = value
End Set
End Property
End Class
My Bridge class:
Public Class Accounts_Bridge
Shared conStr As String = Windows.Application.Current.FindResource("connectionString")
Public Function Update(mc As AccountsData) As Boolean
Dim con As New OleDb.OleDbConnection(conStr)
Dim isSuccessful As Boolean = False
Try
Dim sql As String = "UPDATE Users SET UserName = #user, UserPassword = #pass, UserRole = #role, UserFullname = #name, UserActive = #active WHERE UserID = #id"
Dim cmd As New OleDb.OleDbCommand(sql, con)
cmd.Parameters.Add("#id", OleDbType.Integer).Value = mc.UserID
cmd.Parameters.Add("#user", OleDbType.VarChar).Value = mc.UserName
cmd.Parameters.Add("#pass", OleDbType.VarChar).Value = mc.UserPassword
cmd.Parameters.Add("#role", OleDbType.VarChar).Value = mc.UserRole
cmd.Parameters.Add("#name", OleDbType.VarChar).Value = mc.UserFullname
cmd.Parameters.Add("#active", OleDbType.Boolean).Value = mc.UserActive
con.Open()
Dim i As Integer = cmd.ExecuteNonQuery() 'Always Returns 0
If i > 0 Then
isSuccessful = True
Else
isSuccessful = False
End If
Catch ex As Exception
MsgBox(ex.Message)
Finally
con.Close()
End Try
Return isSuccessful
End Function
End Class
Issue 1: user is a reserved word
user is a reserved word in Access/OleDB.
Hence you need to escape the term as [user] so that the query treats it as the column name.
Issue 2: Parameters position
Unlike SQL Server, Access/OleDB doesn't use named parameters; they are just positional placeholders.
Thus, you must supply the parameter values in the exact order listed in the SQL query.
Recommendation(s)
1.0 You should stop using AddWithValue() which this topic had been highly discussed and recommended in Stack Overflow Community.
1.1 Instead, you need to pass OleDbType for each parameter and be sure that the data type and length parsed must match the table column's type.
2.0 Must declare both OleDbConnection and OleDbCommand with Using statements (these objects are disposable). It's very important that the Connection is disposed.
2.1 The connection will be disposed automatically once the process is ended for success and failure scenario. Hence, you no need to con.Close() manually in the finally block.
For fixing the above issues, your code should be as below:
Public Function Update(mc As AccountsData) As Boolean
Using con As New OleDb.OleDbConnection(conStr)
Dim isSuccessful As Boolean = False
Try
Dim sql As String = "UPDATE Users SET UserName = #user, UserPassword = #pass, UserRole = #role, UserFullname = #name, UserActive = #active WHERE UserID = #id"
Using cmd As New OleDb.OleDbCommand(sql, con)
cmd.Parameters.Add("#user", OleDbType.VarChar).Value = mc.UserName
cmd.Parameters.Add("#pass", OleDbType.VarChar).Value = mc.UserPassword
cmd.Parameters.Add("#role", OleDbType.VarChar).Value = mc.UserRole
cmd.Parameters.Add("#name", OleDbType.VarChar).Value = mc.UserFullname
cmd.Parameters.Add("#active", OleDbType.Boolean).Value = mc.UserActive
cmd.Parameters.Add("#id", OleDbType.Integer).Value = mc.UserID
con.Open()
Dim i As Integer = cmd.ExecuteNonQuery()
If i > 0 Then
isSuccessful = True
Else
isSuccessful = False
End If
End Using
Catch ex As Exception
MsgBox(ex.Message)
End Try
Return isSuccessful
End Using
End Function

How to call the result of a function from a class in Vb.Net?

I would like to know how to call the result of a function that is in another class, in Visual Basic .Net, to then use that result for comparison in an if?
I want to call the result of the SubtractBalance function, specifically, if there is in it, I would like to have it in the class from where I want to call it(FRM_CashWithdrawal2).
I am simulating an ATM. Form FRM_CashWithdrawal2 calls two forms. One is for the impression of the receipt after the desired amount to be withdrawn is entered and the other is for the same procedure but without receipt in order to withdraw the money at the end. Otherwise, the program launches the Message: "Insufficient Funds." When I call the function in this way: oConnection.SubtractBalance (FRM_InsertCardID.TXB_CardID.Text), the SubtractBalance function is evaluated, when the fund is insufficient, it throws the message but also calls the previously mentioned forms. I wish that when you send the message: "Insufficient Funds", do not call those forms.
Thanks in advance.
Imports System.Data.SqlClient
Public Class FRM_CashWithdrawal2
Dim oConnection As New clsDBConnection
Private Sub BTN_Ok_Click(sender As Object, e As EventArgs) Handles BTN_Ok.Click
If TXB_Amount_to_Withdraw.Text.Length = 0 Then
MsgBox("You must fill the field.")
Return
End If
If TXB_Amount_to_Withdraw.Text = "0" Then
MsgBox("Enter the amount to withdraw.")
Return
End If
Dim intAmount As Integer
If Not Integer.TryParse(TXB_Amount_to_Withdraw.Text, intAmount) Then
MessageBox.Show("Please enter a value in the field.")
Return
End If
Select Case intAmount
Case > 10000
MsgBox("It is only possible to withdraw up to RD $ 10000.00 at ATMs.")
Return
End Select
Dim NumMultiple1 = intAmount Mod 100
Dim NumMultiple2 = intAmount Mod 200
Dim NumMultiple3 = intAmount Mod 500
Dim NumMultiple4 = intAmount Mod 1000
Dim NumMultiple5 = intAmount Mod 2000
oConnection.SubtractBalance(FRM_InsertCardID.TXB_CardID.Text)
If NumMultiple1 = 0 OrElse NumMultiple2 = 0 OrElse NumMultiple3 = 0 OrElse NumMultiple4 = 0 OrElse NumMultiple5 = 0 Then
Dim Answer = MessageBox.Show("Do you want to print a receipt?", "Print Receipt", MessageBoxButtons.YesNo)
If Answer = DialogResult.Yes Then
FRM_RemoveYourCard.Show()
Me.Hide()
Else
FRM_RemoveYourCard1.Show()
Me.Hide()
End If
Else
MsgBox("You can only make withdrawals on multiple tickets of RD $ 100.00, RD $ 200.00, RD $ 500.00, RD $ 1000.00 and RD $ 2000.00 pesos.")
End If
End Sub
End Class
Public Class clsDBConnection
Private _strUserDB As String
Private _strPassDB As String
Private _strNameDB As String
Private _strSRVName As String
Private _strConnection As String
Private adAdaptator As SqlDataAdapter
Private tbTable As DataTable
Private drRegister As SqlDataReader
Public strComando As String
Public _Error As Boolean
Public _Menssage As String
Public Sub New()
With ATMApp3.My.Settings
_strSRVName = .strNameSRV.ToString
_strNameDB = .strNameDB.ToString
_strUserDB = .strUserDB
_strPassDB = .strPassUserDB
End With
_strConnection = "Data Source=JOVALLES-PC\SQLSERVEREX;Initial Catalog=" & _strNameDB & ";User ID=" & _strUserDB & ";Password=" & _strPassDB
Try
Dim dbConnection As New System.Data.SqlClient.SqlConnection(_strConnection)
dbConnection.Open()
MsgBox("CONNECTED")
Catch ex As Exception
MsgBox("Error to connect due to: " + ex.ToString)
End Try
End Sub
Public Function Modify(ByVal pCard As String, ByVal pBalance As Integer) As String
Dim Output As String = "It was modified correctly."
Dim dbConnection As New System.Data.SqlClient.SqlConnection(_strConnection)
Dim cmd As New SqlClient.SqlCommand("up_modify_balance", dbConnection)
cmd.CommandType = CommandType.StoredProcedure
Try
If dbConnection.State = ConnectionState.Closed Then
dbConnection.Open()
End If
With cmd.Parameters
.AddWithValue("#Num_Card", pCard)
.AddWithValue("#Balance", pBalance)
End With
cmd.ExecuteNonQuery()
Catch ex As Exception
Output = "It was not modified due to:" + ex.ToString
dbConnection.Close()
End Try
Return Output
End Function
Public Function SubtractBalance(ByVal pCard As String) As SqlDataReader
Dim dbConnection As New System.Data.SqlClient.SqlConnection(_strConnection)
Dim cmd As New SqlClient.SqlCommand("up_consult_balance", dbConnection)
cmd.CommandType = CommandType.StoredProcedure
With cmd.Parameters
.AddWithValue("#Num_Card", pCard)
End With
Try
If dbConnection.State = ConnectionState.Closed Then
dbConnection.Open()
End If
drRegister = cmd.ExecuteReader
If drRegister.Read Then
Dim Subtract As Double
Dim CurrentBalance As Double = CStr(drRegistros("BALANCE_AVAILABLE"))
Subtract = (BalanceActual - FRM_CashWithdrawal2.TXB_Amount_To_Withdraw.Text)
If CurrentBalance < FRM_CashWithdrawal2.TXB_Amount_To_Withdraw.Text Then
MsgBox("Insufficient funds.")
Else
Modify(FRM_InsertCardID.TXB_CardID.Text, Subtract)
End If
Else
_Error = True
_Message = "There is not data"
dbConnection.Close()
Return Nothing
End If
Catch ex As Exception
MsgBox("It was not modified due to:" + ex.ToString)
dbConnection.Close()
End Try
End Function
End Class
I don't see the reason why your SubtractBalance function returns an SqlDataReader.
Instead I would recommend returning a boolean. True if they have money to withdrawal, false if not.
Then you could code it as...
If oConnection.SubtractBalance(FRM_InsertCardID.TXB_CardID.Text) Then
' Rest of processing code here processing
Else
' Tell them insufficient balance here
End If
If this isn't the answer you're looking for can you be more specific about the function return value that you wish to get?
Once a class is initialized, you can get the result of a public function by setting a variable to it's return:
'in a FRM_CashWithdrawal2 instance:
Dim result as SqlDataReader = oConnection.SubtractBalance(pCardString)
Hope it helps.

Failed to convert parameter value from a List`1 to a String

I am getting the error message:
"Failed to convert parameter value from a List`1 to a String"
and I am not sure how to correct the issue. It happens when I attempt to save a cleaningList to a Cleaner object in a database.
I am very new to visual basic and appreciate any feedback to help make this program work.
Public Class FrmMain
Dim currentRoom As String
Dim lastId As Integer
Dim cleaners As New BindingList(Of Cleaner)
'new instance of cleaner and storing it in a reference variable
Dim currentCleaner As New Cleaner()
'-------------Functions----------------
Private Function connectWithDb() As SqlConnection
'create a connection string
Dim connectionString As String = "Server=(LocalDB)\MSSQLLocalDB;Integrated Security=true;AttachDbFileName=C:\Users\Julia\Desktop\JklimeckFinalProject\JklimeckFinalProject\cleanerLists.mdf;"
'create connection object and tell it how to connect using connectionString
Dim dbConnection As New SqlConnection(connectionString)
'open the connection
dbConnection.Open()
'return the connection
Return dbConnection
End Function
'function to change the list to a string seperated by commas
Public Function changeToString() As String
'turn the list of strings into a single string for the database
'trim the leading white space so it won't show up when the list is
'converted back later
currentCleaner.CleaningList = LTrim(String.Join(",", currentCleaner.ItemList.ToArray()))
Return currentCleaner.CleaningList
End Function
'public function to get index of items that are selected
Public Function GetAllItems(index As Integer) As CheckState
End Function
'function to generate a cleaning list
Public Function getCleanList() As List(Of String)
'if statement to display tasks in lbxTasks
Dim indexChecked As Integer
'variable to hold the tasks that are listed depending on the room
'selected ' for current cleaner
Dim itemList As New List(Of String)
'determine the room and create the list of tasks depending on the checked boxes
If currentRoom = "Living Room" Then
itemList.AddRange(currentCleaner.LivRoomTasks)
ElseIf currentRoom = "Kitchen" Then
itemList.AddRange(currentCleaner.KitchenTasks)
ElseIf currentRoom = "Bathroom" Then
itemList.AddRange(currentCleaner.BathroomTasks)
ElseIf currentRoom = "Bedroom" Then
itemList.AddRange(currentCleaner.BedroomTasks)
ElseIf currentRoom = "Dining Room" Then
itemList.AddRange(currentCleaner.DinRoomTasks)
ElseIf currentRoom = "Office" Then
itemList.AddRange(currentCleaner.OfficeTasks)
ElseIf currentRoom = "Laundry Room" Then
itemList.AddRange(currentCleaner.LauRoomTasks)
ElseIf currentRoom = "General" Then
itemList.AddRange(currentCleaner.GeneralTasks)
End If
For Each indexChecked In cbxRoomItems.CheckedIndices
lbxTasks.Items.Add(itemList.Item(indexChecked).ToString)
Next
Return itemList
End Function
'function to seperated the string version of the list
Public Function changeToList() As List(Of String)
'change the comma separated sting back to a list by spliting it at the commas
lbxTasks.Items.AddRange(currentCleaner.CleaningList.Split(New Char() {","c}))
Return currentCleaner.ItemList
End Function
Private Sub FrmMain_Load(sender As Object, e As EventArgs) Handles Me.Load
'when the application loads, show list of cleaners and display by name
lbxNames.DataSource = cleaners
lbxNames.DisplayMember = "Name"
Dim dbConnection As SqlConnection = connectWithDb()
'string of sql
Dim sqlString As String = "SELECT * FROM Cleaner"
'command object pass in what to run and the object
Dim selectCommand As New SqlCommand(sqlString, dbConnection)
'place in a try catch block to keep exceptions from crashing application
Try
'variable to hold the sqlDataReader object
Dim reader As SqlDataReader = selectCommand.ExecuteReader()
If reader.HasRows Then
'read is boolean
While reader.Read
'call the sub
populateCleaners(reader)
End While
End If
reader.Close()
'determine the highest ID number in the database
'and store it in a class level variable so we can access it
'where ever it is needed
Dim identSql As String = "SELECT IDENT_CURRENT('Cleaner') as lastID"
Dim identCom As New SqlCommand(identSql, dbConnection)
Dim identReader As SqlDataReader = identCom.ExecuteReader
If identReader.HasRows Then
identReader.Read()
lastId = CInt(identReader.Item("lastId"))
End If
Catch ex As Exception
End Try
'close and dispose the connection to the db
dbConnection.Close()
dbConnection.Dispose()
End Sub
'Sub to populate the database with a new character
Private Sub populateCleaners(reader As SqlDataReader)
Dim dbCleaner As New Cleaner()
changeToString()
'get info from reader and store into new object
dbCleaner.Id = CInt(reader.Item("Id"))
dbCleaner.Name = reader.Item("Name").ToString
dbCleaner.CleaningList = reader.Item("CleaningList").ToString
'add to binding list
cleaners.Add(dbCleaner)
End Sub
'----------------Butttons------------------
'add to list button
Private Sub btnClean_Click(sender As Object, e As EventArgs) Handles btnClean.Click
'label to show the correct list is being displayed
lblCurrentCleaner.Text = currentCleaner.Name
getCleanList()
End Sub
'save cleaning list
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
Dim newCleaner As New Cleaner()
'referencing object and assigning it to the Name property for the new cleaner
newCleaner.Name = txtName.Text
'exception if the user does not enter a name
Try
newCleaner.Name = txtName.Text
Catch ex As Exception
MessageBox.Show("a cleaner has no name")
End Try
For ctr = 0 To lbxTasks.Items.Count - 1
newCleaner.ItemList.Add(lbxTasks.Items(ctr).ToString)
'change this list to a string
changeToString()
Next
newCleaner.CleaningList = changeToString()
lbxTasks.Items.Clear()
cleaners.Add(newCleaner)
currentCleaner = newCleaner
'update a cleaning list if the Id is already in the database, or create a new object
Dim dbConnection As SqlConnection = connectWithDb()
Dim sqlString As String
If currentCleaner.Id > 0 Then
sqlString = "UPDATE Cleaner SET Name = #name, CleaningList = #cleaningList WHERE Id = #id"
Else
sqlString = "INSERT INTO Cleaner (Name, CleaningList) VALUES(#name, #cleaningList)"
'increment the last Id and save that id number to the new entry in the db
lastId += 1
currentCleaner.Id = lastId
End If
Dim com As New SqlCommand(sqlString, dbConnection)
'set the values of current cleaner in the database
com.Parameters.Add("#id", SqlDbType.Int).Value = currentCleaner.Id
com.Parameters.Add("#name", SqlDbType.VarChar).Value = currentCleaner.Name
com.Parameters.Add("#cleaningList", SqlDbType.NVarChar).Value = currentCleaner.ItemList
Try
Dim result = com.ExecuteNonQuery()
MessageBox.Show(result.ToString)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
I have a Cleaner class that stores the public properties.
In the program the user clicks on different buttons that populate a checklistbox with different items found in that room, by selecting the items and clicking btnClean it populates a listbox with a list of tasks associated with the items the user selected. My problem seems to be centered around that list; it is stored in a list(of String), but I made a function to turn that list into a single string separated by commas so it can be stored in a database and another function to separated that list so it can be displayed back in the listbox when the user's name is selected.
I am not sure where it is I am going wrong.
The exception is being thrown in:
'save cleaning list
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
Dim newCleaner As New Cleaner()
'referencing object and assigning it to the Name property for the new cleaner
newCleaner.Name = txtName.Text
'exception if the user does not enter a name
Try
newCleaner.Name = txtName.Text
Catch ex As Exception
MessageBox.Show("a cleaner has no name")
End Try
For ctr = 0 To lbxTasks.Items.Count - 1
newCleaner.ItemList.Add(lbxTasks.Items(ctr).ToString)
'change this list to a string
changeToString()
Next
lbxTasks.Items.Clear()
cleaners.Add(newCleaner)
currentCleaner = newCleaner
'update a cleaning list if the Id is already in the database, or create a new object
Dim dbConnection As SqlConnection = connectWithDb()
Dim sqlString As String
If currentCleaner.Id > 0 Then
sqlString = "UPDATE Cleaner SET Name = #name, CleaningList = #cleaningList WHERE Id = #id"
Else
sqlString = "INSERT INTO Cleaner (Name, CleaningList) VALUES(#name, #cleaningList)"
'increment the last Id and save that id number to the new entry in the db
lastId += 1
currentCleaner.Id = lastId
End If
Dim com As New SqlCommand(sqlString, dbConnection)
com.Parameters.Add("#name", SqlDbType.VarChar).Value = currentCleaner.Name
com.Parameters.Add("#cleaningList", SqlDbType.NVarChar).Value = currentCleaner.ItemList
Try
Dim result = com.ExecuteNonQuery()
MessageBox.Show(result.ToString)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Again thank you for any suggestions/help!

Procedure or function 'p_xxx ' has too many arguments specified

I get the error at this line: sqlDataAdapDelProtocol.Fill(dsDelProtocol, "dsProtocols"), I dint understand why. The error states : Procedure or function p_GetLinkedProcuduresProtocol has too many arguments specified
Protected Sub btnDeletePTC_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim sqlString As String = String.Empty
Dim PTC_ID As Integer
sqlString = "p_GetLinkedProcuduresProtocol"
Dim sqlConnDelProtocol As New SqlClient.SqlConnection(typicalConnectionString("MyConn").ConnectionString)
sqlConnDelProtocol.Open()
Dim sqlDataAdapDelProtocol As New SqlClient.SqlDataAdapter(sqlString, sqlConnDelProtocol)
sqlDataAdapDelProtocol.SelectCommand.CommandType = CommandType.StoredProcedure
Dim sqlParProtocolName As New SqlClient.SqlParameter("#PTC_ID", SqlDbType.Int, 255)
sqlDataAdapDelProtocol.SelectCommand.Parameters.Add(sqlParProtocolName)
Dim dsDelProtocol As New DataSet
Dim MessageAud = "Are you sure you want to delete this question, the question is linked to:"
Dim MessageNoAud = "Are you sure you want to delete this question"
sqlDataAdapDelProtocol.SelectCommand.Parameters.AddWithValue("PTC_ID", PTC_ID)
sqlDataAdapDelProtocol.Fill(dsDelProtocol, "dsProtocols")
If dsDelProtocol.Tables("dsProtocols").Rows.Count > 0 Then
lblMessageSure.Text = (CType(MessageAud, String))
For Each dr As DataRow In dsDelProtocol.Tables(0).Rows
lblAudits = (dr("dsProtocols"))
Next
Else
lblMessageSure.Text = (CType(MessageNoAud, String))
End If
Dim success As Boolean = False
Dim btnDelete As Button = TryCast(sender, Button)
Dim row As GridViewRow = DirectCast(btnDelete.NamingContainer, GridViewRow)
Dim cmdDelete As New SqlCommand("p_deleteProtocolStructure")
cmdDelete.CommandType = CommandType.StoredProcedure
cmdDelete.Parameters.AddWithValue("PTC_ID", PTC_ID)
Call DeleteProtocol(PTC_ID)
conn = NewSqlConnection(connString, EMP_ID)
cmdDelete.Connection = conn
If Not conn Is Nothing Then
If conn.State = ConnectionState.Open Then
Try
success = cmdDelete.ExecuteNonQuery()
Call UpdateProtocolNumbering(PTS_ID)
txtAddPTCNumber.Text = GetNextNumber(PTS_ID)
Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), "TreeView", _
"<script language='javascript'>" & _
" parent.TreeView.location='TreeView.aspx?MainScreenURL=Protocols.aspx&PTS_ID=" & PTS_ID & "';" & _
"</script>")
conn.Close()
Catch ex As Exception
success = False
conn.Close()
Throw ex
End Try
End If
End If
If success = True Then
Call GenerateQuestionsGrid()
Call Message(Me, "pnlMessage", "Question successfully deleted.", Drawing.Color.Green)
Else
Call Message(Me, "pnlMessage", "Failed to delete Question.", Drawing.Color.Red)
End If
End Sub
You are adding the same parameter twice, once without a value, then with a value. Instead of adding it another time, set the value on the parameter that you already have.
Replace this:
sqlDataAdapDelProtocol.SelectCommand.Parameters.AddWithValue("PTC_ID", PTC_ID)
with this:
sqlParProtocolName.Vaue = PTC_ID
Side note: Always start parameter names for Sql Server with #. The parameter constructor will add it if it's not there so it will work without it, but this is an undocumented feature, so that could change in future versions.