VB.NET - Stored procedure runs but parameters aren't working - sql

I have the following bit of code:
Dim SQLCon As New SqlConnection
Dim cmd As New SqlCommand
Dim ds As New DataSet
SQLCon.ConnectionString = ConfigurationSettings.AppSettings("myConnString")
SQLCon.Open()
cmd.CommandType = CommandType.StoredProcedure
'run the stored procedure based on the view selected
If rdolstView.Items(0).Selected Then
cmd = New SqlCommand("spCondensedView", SQLCon)
ElseIf rdolstView.Items(1).Selected Then
cmd = New SqlCommand("spExtendedView", SQLCon)
End If
'filter by what the user searched for
If ddlSearchBy.SelectedValue = "Member" Then
cmd.Parameters.AddWithValue("#MbrNum", txtSearchFor.Text)
ElseIf ddlSearchBy.SelectedValue = "Assistant" Then
cmd.Parameters.AddWithValue("#AssignedAsst", ddlUWAssistants.SelectedValue)
ElseIf ddlSearchBy.SelectedValue = "Rep" Then
cmd.Parameters.AddWithValue("#Rep", txtSearchFor.Text)
ElseIf ddlSearchBy.SelectedValue = "Dept Assistant" Then
cmd.Parameters.AddWithValue("#DeptAsst", txtSearchFor.Text)
ElseIf ddlSearchBy.SelectedValue = "Creator" Then
cmd.Parameters.AddWithValue("#Creator", txtSearchFor.Text)
End If
Dim da As New SqlDataAdapter(cmd)
da.Fill(ds)
SQLCon.Close()
My problem is that the parameters don't seem to be working. Both stored procedures are supposed to take the optional parameter (either #MbrNum, #AssignedAsst, #Rep, #DeptAsst, or #Creator) and filter by it in its WHERE clause.
I've confirmed that this is working properly when I run the stored procedures manually in SQL Server Management Studio. I've also confirmed that the If/ElseIf statements are validating as true properly. So my code is definitely hitting the AddWithValue() statements when it's supposed to.
My returned result, however, is the full dataset without the filters applied, as if I ran the stored procedure with no parameters specified.
Any help would be awesome. Thanks!

Try specifying the a Command.Type...Set this when you create the command object.
cmd.CommandType = CommandType.StoredProcedure
By default it's set as Text I believe... Also wrap your connection and command's in Using statements so they are properly handled when done...

Related

Hi folks. I am trying to update an app to VB dot net from vb6 and have enouctered a really basic problem. I will add the code of course in a sec. I

Trying to update an old VB6 app to VB.Net. I am having trouble with syntax, I think. In any case it is a simple matter of inserting a new record to the autolog table. (code below).
I would like to ask something else that is often not documented too. It seems that I have to use command builders and so on - is there no way I can simply use an SQL statement and execute it against the background table? The tables are in Access while I am developing but will be scaled up on the final release of the software.
I have altered my code to the following by making use of the error suggestions at the foot of mygui.
It now looks like this and the only thing is that it is throwing a logic error at me which is that every end function must have a preceding "function". Perhaps I am being a little bit dim
Function MAutolog(ByVal Action As String) As Boolean
Dim SQL = "Insert Into Autolog (Action) Values (#Action)"
Using con As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\PC User\Documents\Freightmaster\resources\freightmaster.accdb"),
cmd As New OleDb.OleDbCommand(SQL, con)
cmd.Parameters.Add("#Action", OleDb.OleDbType.VarChar).Value = Action
con.Open()
cmd.ExecuteNonQuery()
End Using
MAutolog = True
End Function
I would like to thank you for your help in advance. I can not tell you how much I will appreciate it.
Code
Module ModFunctions
Function MAutolog(ByVal UserID As Long, ByVal Action As String) As Boolean
Dim dbprovider As String
Dim dbsource As String
Dim mydocumentsfolder As String
Dim fulldatabasepath As String
Dim TheDatabase As String
Dim SQL As String
Dim DS As New DataSet
Dim da As OleDb.OleDbDataAdapter
Dim con As New OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\PC User\Documents\Freightmaster\resources\freightmaster.accdb")
con.Open()
'----------------------------
SQL = "Select * from Autolog"
da = New OleDb.OleDbDataAdapter(SQL, con)
da.Fill(DS, "Log")
con.Close()
Dim CB As New OleDb.OleDbCommandBuilder(da)
Dim DSNEWROW As DataRow
DSNEWROW = DS.Tables("Log").NewRow()
DSNEWROW.Item("UserID") = UserID
DSNEWROW.Item("Action") = Action
DS.Tables("log").Rows.Add(DSNEWROW)
da.Update(DS, "log")
MAutolog = True
End function
Database objects like Connection and Command use unmanaged code and need their Dispose methods to release these resources. Either call this method on these objects or use Using...End Using blocks which will do this for you even if there is an error. In this code, both the Connection and Command are included in the Using block by separating them be a comma.
By Val is the default so is not necessary.
Always use parameters to avoid sql injection. Using values directly from user input can allow malicious code to be executed on your database. The value of a parameter is not considered as executable code by the database.
OleDb does not care about parameter names. You could just as easily use ? in the sql statement. I use names for readability. You do need some sort of name to add the parameter. OleDb considers the position of the parameter in the sql statement. The position must match the order that the parameters are added to the parameters collection.
This is the code for the Insert if UserID in an auto-number field. You do not provide a value for auto-number fields. The database will handle that.
Function MAutolog(Action As String) As Boolean
Dim SQL = "Insert Into Autolog (Action) Values (#Action)"
Using con As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\PC User\Documents\Freightmaster\resources\freightmaster.accdb"),
cmd As New OleDbCommand(SQL, con)
cmd.Parameters.Add("#Action", OleDbType.VarChar).Value = Action
con.Open()
cmd.ExecuteNonQuery()
End Using
MAutolog = True
End Function
If UserID is not auto-number
Function MAutolog(UserID As Long, Action As String) As Boolean
Dim SQL = "Insert Into Autolog (UserID, Action) Values (#UserID, #Action)"
Using con As New OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\PC User\Documents\Freightmaster\resources\freightmaster.accdb"),
cmd As New OleDbCommand(SQL, con)
cmd.Parameters.Add("#UserID", OleDbType.Integer).Value = UserID
cmd.Parameters.Add("#Action", OleDbType.VarChar).Value = Action
con.Open()
cmd.ExecuteNonQuery()
End Using
MAutolog = True
End Function

What would cause my dataset to drop a row?

I have a SQL statement that, when ran in SSMS, returns 6 rows. After attaching the statement to the command text of a VB.NET SQLCommand with a command type of Text, reading it with a SqlDataReader, and attaching it to a dataset, the returned dataset only has 5 rows.
At first, I assumed it was an issue with the data. However, after several bouts of removing and adding rows to the source table with varying data, it was obvious that I was always getting the total row count - 1. I then decided to just use a SQLDataAdapter to populate the DataSet and the proper number of rows was returned.
Dim ds As New DataSet
Dim sqlCmd as New SqlCommand
Dim sqlCn As New SqlConnection
Dim sqlR As New SqlCommand
sqlCn.ConnectionString = "SomeConnectionString"
With sqlCmd.CommandText = "Select * from DummyTable"
.CommandType = CommandType.Text
.Connection = sqlCn
End With
sqlCn.Open()
sqlR = sqlCmd.ExecuteReader
sqlR.Read()
If sqlR.HasRows() Then
ds.Tables.Add("DummyTable")
ds.Tables(0).Load(sqlR)
return ds
End If
From here, I'm expecting to see the 6 rows from DummyTable. Instead, I'm seeing only 5.
However, if I use the following:
Dim da as SqlDataAdapter
Using sqlCn
da.SelectCommand = New SqlCommand(sqlCmd.CommandText, sqlCn)
da.Fill(ds)
End Using
Return ds
I get the full 6 rows. Is there something I'm missing about the way a DataSet's Tables.Add(tableName) or Tables(n).Load(dataReader) works? I had never worked with SqlDataReaders prior to this and was told to stick with them as our other projects use them.
Your code is already reading the first line of the query with the line sqlR.Read(). This line is unnecessary in your code. Remove it and it will work fine.
Also SqlCommand, SqlConnection and SqlDataReader implement iDisposable, so be sure to use using-statement with them:
Using sqlCn As New SqlConnection("SomeConnectionString")
sqlCn.Open()
Using sqlCmd as New SqlCommand
With sqlCmd.CommandText = "Select * from DummyTable"
.CommandType = CommandType.Text
.Connection = sqlCn
End With
Using sqlR As SqlDataReader = sqlCmd.ExecuteReader
If sqlR.HasRows() Then
Dim ds As New DataSet
ds.Tables.Add("DummyTable")
ds.Tables(0).Load(sqlR)
return ds
End If
End Using
End Using
End Using

Self learning on vb.net

Currently I'm trying to understand and learn new code commands for vb.net. i have came across three codes while researching which is
"SELECT staff_id,pass_word FROM userlogin WHERE staff_id = #staff_id AND pass_word = #pass_word")
Second code:
Dim uName As New OleDbParameter("#staff_id", SqlDbType.VarChar)
Third and last:
uName.Value = txtstaffid.Text
myCommand.Parameters.Add(uName)
What are the uses of #pass_word code when you have already typed the pass_word column, Oledbparameter, and Parameters.Add?
The following code shows a bit more complete picture of what the code is doing. The Using...End Using blocks ensure that your objects are closed and disposed even if there are errors. Of course, in a real application, passwords would never be stored as plain text (too easy to hack). They would be salted and hashed but that is for another day.
Private Sub CheckPassword()
'This line assigns a Transact SQL command to a string variable.
'It will return a record with 2 columns. The #staff_id and #pass_word are parameter placeholders.
'The use of parameters limits the possibilit of SQL injection with malicious input be the user
'typing in the text box.
Dim strSQL = "SELECT staff_id,pass_word FROM userlogin WHERE staff_id = #staff_id AND pass_word = #pass_word;"
Using cn As New SqlConnection("Your connection string")
'Pass the command string and the connection to the constructor of the command.
Using cmd As New SqlCommand(strSQL, cn)
'It is unneccessary to create a command variable.
'The .Add method of the commands Parameters collection will create a parameter.
cmd.Parameters.Add("#staff_id", SqlDbType.VarChar).Value = txtstaffid.Text
cmd.Parameters.Add("#pass_word", SqlDbType.VarChar).Value = txtPassword.Text
cn.Open()
Using dr As SqlDataReader = cmd.ExecuteReader
'All we really need to know is whether we returned a row.
If dr.HasRows Then
MessageBox.Show("Login Successful")
Else
MessageBox.Show("Login Failed")
End If
End Using
End Using
End Using
End Sub

Selecting different connection strings for data gridview

Why is this not straight-forward? I have two databases that contain a log-table each. I have a stored procedure that extracts the data from the table. I have a datagridview on a windows form, and a drop-down box to select the connection string for the respective databases. On selection of the conn string, I want to change the datagridview to contain the log messages in the selected database.
My code:
Select Case cboConnection.Text
Case "CP DEV"
LogConnectionString = "Data Source=SAMBAR.gofast.com;Initial Catalog=CPDev;User ID=gofastconfig;Password=gofastdev;"
Case "CP LIVE"
LogConnectionString = "Data Source=SAMBAR.gofast.com;Initial Catalog=CPLive;User ID=gofastconfig;Password=gofastlive;"
End Select
Dim cmd As New SqlCommand("dbo.getLogMessages")
Using con As New SqlConnection(LogConnectionString)
Using sda As New SqlDataAdapter()
cmd.Connection = con
cmd.CommandType = CommandType.StoredProcedure
sda.SelectCommand = cmd
sda.Fill(Me.CustomerPulseDBDataSet1)
con.Close()
gridLog.DataSource = Me.CustomerPulseDBDataSet1.Tables(0)
End Using
End Using
First, I don't see you open your connection. Then, you got it a bit up side down...
Using con As New SqlConnection(LogConnectionString)
con.Open()
Using cmd As New SqlCommand("dbo.getLogMessages", con)
cmd.CommandType = CommandType.StoredProcedure
Using da As New SqlDataAdapter(cmd)
' We need to clear out old data before reloading if same DS instance used
If Me.CustomerPulseDBDataSet1.Tables.Count > 0 Then
Me.CustomerPulseDBDataSet1.Tables.Clear()
End If
da.Fill(Me.CustomerPulseDBDataSet1)
End Using
End Using
con.Close()
End Using
gridLog.DataSource = Me.CustomerPulseDBDataSet1.Tables(0)
Should work perfectly every time

vb error: Value of type 'String' cannot be converted to 'System.Data.SqlClient.SqlCommand'

I'm a novice VB programmer and I'm sure this solution is trivial, however, I am getting the above error when I try to display the results of one of my Stored Procs in SQL Server which doesn't need any parameters. How can I fix this?
My code excerpt:
Dim SQLCmd as SQLCommand = new SQLCommand()
SQLCmd.CommandText = "Exec AllTableCount"
SQLCmd.CommandType = CommandType.StoredProcedure
SQLCmd.Connection = GlobalFunctions.GlobalF.GetDevSQLServerStoredProcedure(SQLCmd.CommandType)
SQLCmd.ExecuteNonQuery()
MsgBox(SQLCmd.ExecuteNonQuery)
Where GetDevSQLServerStoredProcedure is defined in a different file as:
Public Shared Function GetDevSQLServerStoredProcedure(ByVal SQL As String)
Dim DBConn As SQLConnection
Dim DBCommand As SQLDataAdapter
Dim DSPageData As New System.Data.DataSet
DBConn = New SQLConnection(ConfigurationSettings.AppSettings("AMDMetricsDevConnectionString"))
DBCommand = New SQLDataAdapter(SQL) 'This is the line it errors on'
DBCommand.Fill(DSPageData, "Exceptions")
Return DSPageData
End Function
I can see this SP from VS 2008 in the Server Explorer. So the problem seems to be that I don't know how to connect a data adapter to an SP. Just a string query.
Command text should just be the name of the stored procedure as Tim mentioned.
It looks like the problem you are having now is that you are passinging the CommandType to your method GetDevSQLServerStoredProcedure instead of a string.