How to Parameterized Queries with the SqlDataSource (VB) - sql-server

This is my code example to run parameterized query in VB.NET:
Dim sqlconn As New SqlConnection(connectionString)
sqlconn.Open()
Dim cmd As New SqlCommand
cmd.CommandText = "Select * from TAble1 Where SkuCode in (#SKU)"
cmd.Connection = sqlconn
Dim parm As New SqlParameter
parm.Value ="1" 'This is working
parm.ParameterName = "#SKU"
cmd.Parameters.Add(parm)
Dim ds As New DataSet
Dim sqlDa As New SqlDataAdapter(cmd)
sqlDa.Fill(ds)
Dim dt As DataTable
dt = ds.Tables(0)
If dt.Rows.Count > 0 Then
MsgBox("Done")
Else
MsgBox("Not done.")
End If
If I run this example in VB.NET this returns the result successfully.
But there is an issue while trying to get results with multiple in records... this is not working.
Please check and suggest the change we have to do to run in query with parameters.
'parm.Value = "N'1', N'2'" 'this does not work.
'parm.Value = "'1','2'" 'this does not work.
I have tried these parameter value but it does not work.

SQL parameters are scalar and only accept a single value. You can use the sqldbtype.Structured though it gets a bit complicated.
I've found that if you need to pass in a set of parameters for an IN where the number of parameters is dynamics, the most effective way (unfortunately) is:
String interpolation/concatenation without parameters
Loop to build out the parameters and add them to your sqlcommand
LINQ to build out the parameters and add them to your sqlcommand
I've provided an example of the linq option below.
Dim sqlParams As Dictionary(Of String, Integer) = integers.ToDictionary(Function(i) $"#ParamValue{i}", Function(i) i)
Dim ds As New DataSet
Dim dt As DataTable
Using db as new SqlConnection(conn)
conn.open()
Using cmd As New SqlCommand($"SELECT * FROM Table1 WHERE SkuCode IN (-1, {String.Join(", ", sqlParams.Select(Function(f) f.Key))}", db)
cmd.Parameters.AddRange(sqlParams.Select(Function(f) New SqlParameter(f.Key, SqlDbType.BigInt).Value = f.Value).ToArray())
Dim sqlDa As New SqlDataAdapter(cmd)
sqlDa.Fill(ds)
dt = ds.Tables(0)
End Using
End Using
MsgBox(If(dt.Rows.Count > 0, "Done", "Not done"))

Related

Fill a CheckedListbox from a database based on checked values of another CheckedListbox

I am using SQL Server 2016 Visual studio 2017.
Need to fill checkedlistbox2, from my database, based on the value of the SelectedItem of Checkedlistbox1.
I am filling checkedlistbox1 on Form.Load as below:
This code is working.
Private Sub fillChkboxList()
Dim conn As New SqlConnection("Data Source=192.168.200.36;user id=sa;password=XXXX#123;database=XXXXXXX")
Dim sda As New SqlDataAdapter("select DepartmentName, DepartmentID from DepartmentMain where active=1 order by DepartmentName", conn)
Dim dt As New DataTable
sda.Fill(dt)
CheckedListBox1.DataSource = dt
CheckedListBox1.DisplayMember = "DepartmentName"
CheckedListBox1.ValueMember = "DepartmentID"
End Sub
Here I am trying to use a method to fill Checkedlistbox2, which I am calling in the ItemCheck event handler of Checkedlistbox1:
Below Code is not giving required results
Public Function fillChkboxListSub()
Dim i As Integer
Dim conn1 As New SqlConnection("Data Source=192.168.200.36;user id=sa;password=XXXX#123;database=XXXXXXX")
With CheckedListBox2
For i = 0 To CheckedListBox1.Items.Count - 1 Step i + 1
If CheckedListBox1.GetItemCheckState(i) = CheckState.Checked Then
Dim xx As String = (CType(CheckedListBox1.Items(i), DataRowView))("DepartmentID")
Dim sqlstr2 As String = "select SubName,SubDeptID from DepartmentSub where active=1 and DepartmentID in ('" & xx & "') order by SubName"
Dim command2 As New SqlCommand(sqlstr2, conn1)
Dim adpt2 As New SqlDataAdapter(command2)
adpt2.SelectCommand = command2
adpt2.Fill(dt2)
CheckedListBox2.DataSource = dt2
CheckedListBox2.DisplayMember = "SubName"
CheckedListBox2.ValueMember = "SubDeptID"
End If
Next
End With
End Function
This function I am calling on:
Private Sub CheckedListBox1_ItemCheck(sender As Object, e As ItemCheckEventArgs) Handles CheckedListBox1.ItemCheck
fillChkboxListSub()
End Sub
I am not getting the result.
If I check the (DepartmentName) in checkedlistbox1, SubDeptName should load in checkedlistbox2. If I deselect the same in checkedlistbox1, it should be deleted or removed from checkedlistbox2Please help with working code example.
Thanks in Advance
Most database objects need to be disposed. Connections, Commands, and DataReaders have a Dispose method that must be called to release unmanaged resources that they use. It is made easy for us with Using...End Using blocks that ensure that Dispose is called even if there is an error.
The order of setting the DataSource, DisplayMember, and ValueMember is important. Setting DataSource should be last line. If you set ValueMember before DataSource no action is triggered. If you set Datasource first, the box will bind value member for you. Then, you're going to set a new ValueMember (the one you want) and box will have to re-wire binding. So, if you set DataSource last, bindings will happen only once.
You can use the CheckedItems collection to loop through. Add eacn item to a list. After the loop use Join with a comma separator to prepare the In clause for the sql string. I used an interpolated string to build the sql string indicated by the preceding $. Variables can then be inserted in line surrounded by { } .
Private CnString As String = "Data Source=192.168.200.36;user id=sa;password=XXXX#123;database=XXXXXXX"
Private Sub fillChkboxList1()
Dim dt As New DataTable
Using conn As New SqlConnection(CnString),
cmd As New SqlCommand("select DepartmentName, DepartmentID from DepartmentMain where active=1 order by DepartmentName", conn)
conn.Open()
Using reader = cmd.ExecuteReader
dt.Load(reader)
End Using
End Using
CheckedListBox1.DisplayMember = "DepartmentName"
CheckedListBox1.ValueMember = "DepartmentID"
CheckedListBox1.DataSource = dt
End Sub
Public Sub fillChkboxList2()
Dim lst As New List(Of Integer)
For Each item In CheckedListBox1.CheckedItems
Dim drv = DirectCast(item, DataRowView)
Dim DepId As Integer = CInt(drv("DepartmentId"))
lst.Add(DepId)
Next
Dim DepIdString = String.Join(",", lst)
Dim sql As String = $"select SubName,SubDeptID from DepartmentSub where active=1 and DepartmentID in ({DepIdString}) order by SubName"
Debug.Print(sql) 'See if your select string looks correct.
Dim dt As New DataTable
Using cn As New SqlConnection(CnString),
cmd As New SqlCommand(sql, cn)
cn.Open()
Using reader = cmd.ExecuteReader
dt.Load(reader)
End Using
End Using
CheckedListBox2.DisplayMember = "SubName"
CheckedListBox2.ValueMember = "SubDeptID"
CheckedListBox2.DataSource = dt
End Sub

incorrect syntax near "=" in vb.net

I am a beginner and really need help. I want to display data from the database and assign the values to the textboxes and a combobox on a form, but I get this error
Incorrect syntax near "="
It appears is on this line
myreader = cmd.ExecuteReader
Please - any help?
Sub ref()
Dim conn As New SqlConnection
conn.ConnectionString = ("Data Source=.;Initial Catalog=UEW_ADMISSION_CHEAKER;Integrated Security=True")
conn.Open()
Dim strsql As String
strsql = "SELECT ProgName,MaleCuteOff,FemaleCutOff from CutOff_Point where ProgName=" + cmbCourse.SelectedItem + ""
Dim cmd As New SqlCommand(strsql, conn)
Dim myreader As SqlDataReader
myreader = cmd.ExecuteReader
myreader.Read()
txtFemale.Text = myreader("FemaleCutOff")
txtMale.Text = myreader("MaleCuteOff")
conn.Close()
End Sub
You should always use SQL parameters to pass parameters to SQL - it avoids embarrasing problems like single quotes breaking the query and deliberate SQL injection attacks.
It's probably best to make sure that there is a selected value before trying to use it.
Some things, e.g. database connections, use "unmanaged resources" and it is necessary to use the Dispose() method to make sure that things are cleaned up afterwards. The Using statement is a convenient way to get the computer to take care of that for you.
I didn't see a need for the query to return the value that was passed to it (ProgName).
You will need to adjust the .SqlDbType and .Size to match the database column.
Option Strict On
' ... other code
Sub Ref()
If cmbCourse.SelectedIndex >= 0 Then
Dim sql As String = "SELECT MaleCuteOff, FemaleCutOff FROM CutOff_Point WHERE ProgName = #ProgName"
Dim connStr = "Data Source=.\;Initial Catalog=UEW_ADMISSION_CHEAKER;Integrated Security=True"
Using conn As New SqlConnection(connStr),
cmd As New SqlCommand(sql, conn)
cmd.Parameters.Add(New SqlParameter With {.ParameterName = "#ProgName", .SqlDbType = SqlDbType.VarChar, .Size = 99, .Value = cmbCourse.SelectedItem})
conn.Open()
Dim rdr As SqlDataReader = cmd.ExecuteReader()
If rdr.HasRows Then
rdr.Read()
txtFemale.Text = rdr.GetInt32(0).ToString()
txtMale.Text = rdr.GetInt32(1).ToString()
End If
End Using
End If
End Sub
P.S. Shouldn't UEW_ADMISSION_CHEAKER be UEW_ADMISSION_CHECKER? It's best to have things spelt correctly as it is easier to type them.
First of all this Block of Code is not OK. You could use :
Using....End Using Method.
SqlCommand.Parameters Property for security issues.
Connection Strings and Configuration Files for security issues.
Allow me to rewrite your Code using the above methods.
Private Sub RetrieveAndDisplayCutOff()
Dim sbMale As New StringBuilder
Dim sbFemale As New StringBuilder
Dim strsql As String =
"SELECT MaleCutOff,FemaleCutOff FROM CutOff_Point WHERE ProgName = #ComboItem"
Using conn As New SqlConnection("Data Source=.;Initial Catalog=UEW_ADMISSION_CHEAKER;Integrated Security=True"),
CMD As New SqlCommand(strsql, conn)
CMD.Parameters.Add("#ComboItem", SqlDbType.VarChar).Value = ComboBox1.SelectedItem.ToString
conn.Open()
Using MyReader As SqlDataReader = CMD.ExecuteReader
While MyReader.Read 'Returns False if no more rows
'OP mentioned in comments that these fields were int
sbMale.AppendLine(MyReader.GetInt32(0).ToString)
sbFemale.AppendLine(MyReader.GetInt32(1).ToString)
End While
End Using
End Using
txtMale.Text = sbMale.ToString
txtFemale.Text = sbFemale.ToString
End Sub

Add ORDER BY clause in VB.Net?

How to concatenate
ORDER BY
clause in VB.NET?
Here's what I've tried:
Using command As New SqlCommand()
command.Connection = conn
Dim parameterNames As New List(Of String)(dt_data.RowCount - 2)
For i As Integer = 0 To dt_data.RowCount - 3
Dim parameterName As String = "#meter_num_" & i
Dim meter_number As String = dt_data.Rows(i).Cells(3).Value
command.Parameters.AddWithValue(parameterName, meter_number)
parameterNames.Add(parameterName)
Next
command.CommandText = String.Format("SELECT * FROM customer WHERE cycle = #cycle and meter_num IN ({0})", String.Join(",", parameterNames), ("ORDER BY Client_Name ASC"))
command.Parameters.AddWithValue("#cycle", cycle2last)
Dim da As New SqlDataAdapter(command)
Dim ds As New DataSet
da.Fill(ds, "customer")
Compare_Reading.dt_last2month.DataSource = ds.Tables(0)
End Using
I wanted it to be like this
Select * from table_name
where column_name = #column and column2 = #column2
ORDER BY column_name ASC
To do that in a single instruction you need to replace
Compare_Reading.dt_last2month.DataSource = ds.Tables(0)
With:
Compare_Reading.dt_last2month.DataSource = (From existing As DataRow In ds.Tables(0).Select Order By existing.Item("your_filed_name_to_order_here") Ascending).CopyToDataTable
One of the nice things about List(Of T) is that you don't need to know the size before adding items. It will expand as necessary. So, I deleted the int32 from the constructor.
I think you want dt_data.RowCount -2 in For loop or you will skip the last row. I changed your .AddWithValue to .Add. You will have to check your database for the correct datatypes (I guessed) and adjust the code accordingly.
I think your main problem was in String.Format. You added the 2 parameters but neglected to put in the {1}.
I added a Debug.Print so you can check that your Select looks like you expect. This will appear in the immediate window when you run in debug. It won't effect the release version.
You don't need a DataAdapter or DataSet just a DataTable. Assign the .DataSource outside of the Using block.
I don't think there is any concern about sql injection because you have properly used parameters for all the variables.
Private Sub OPCode(cycle2last As String)
Dim dt As New DataTable
Using conn As New SqlConnection("Your connection string")
Using command As New SqlCommand()
command.Connection = conn
Dim parameterNames As New List(Of String)
For i As Integer = 0 To DataGridView1.RowCount - 2
Dim parameterName As String = "#meter_num_" & i
Dim meter_number As String = DataGridView1.Rows(i).Cells(3).Value.ToString
command.Parameters.Add(parameterName, SqlDbType.VarChar).Value = meter_number
parameterNames.Add(parameterName)
Next
command.CommandText = String.Format("SELECT * FROM customer WHERE cycle = #cycle and meter_num IN ({0}) {1}", String.Join(",", parameterNames), ("ORDER BY Client_Name ASC;"))
command.Parameters.Add("#cycle", SqlDbType.VarChar).Value = cycle2last
Debug.Print(command.CommandText)
conn.Open()
dt.Load(command.ExecuteReader)
End Using
End Using
DataGridView2.DataSource = dt
End Sub

Auto complete textbox from mdf (master SQL Server database file)

I'm trying to use an autocomplete textbox, fed from a SQL Serve .mdf database file.
This is my code:
Dim cmd As New SqlCommand("Select col_name FROM college ", cn)
If cn.State = ConnectionState.Closed Then cn.Open()
Dim ds As New DataSet
Dim sqda As New SqlDataAdapter(cmd)
sqda.Fill(ds, "college")
Dim col As New AutoCompleteStringCollection
Dim i As Integer
For i = 0 To ds.Tables(0).Rows.Count - 1
col.Add(ds.Tables(0).Rows(i)("col_name").ToString())
Next
TextBox1.AutoCompleteSource = AutoCompleteSource.CustomSource
TextBox1.AutoCompleteCustomSource = col
TextBox1.AutoCompleteMode = AutoCompleteMode.Suggest
Since I am using SQL Server, the data not showing in the list.
I think its needs to use character N like
Insert data into SQL Server as:
cmd = New SqlCommand("insert into college (col_name) values (N'" & TextBox1.Text.Trim & "')", cn)
Keep your database objects local so you can control the closing and disposing. Using...End Using blocks handle this even if there is an error.
Always use parameters to avoid Sql injection.
In .net Char supports Unicode so strings (which are arrays of Char) also support Unicode. As long as the field in Sql Server is of type NVarChar. I don't see a problem
Private Sub SetUpAutoComplete()
Dim dt As New DataTable
Using cn As New SqlConnection("Your connection string")
Using cmd As New SqlCommand("Select col_name FROM college ", cn)
cn.Open()
dt.Load(cmd.ExecuteReader)
End Using
End Using
Dim col As New AutoCompleteStringCollection
For Each row As DataRow In dt.Rows
col.Add(row("col_name").ToString)
Next
'Just to check if we have some data
Debug.Print(col.Count.ToString)
TextBox3.AutoCompleteSource = AutoCompleteSource.CustomSource
TextBox3.AutoCompleteCustomSource = col
TextBox3.AutoCompleteMode = AutoCompleteMode.Suggest
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
SetUpAutoComplete()
End Sub
Private Sub InsertCollege()
Using cn As New SqlConnection("Your Connection string")
Using cmd As New SqlCommand("insert into college (col_name) values (#Name)", cn)
cmd.Parameters.Add("#Name", SqlDbType.NVarChar).Value = TextBox1.Text.Trim
cn.Open()
cmd.ExecuteNonQuery()
End Using
End Using
End Sub

How to call a table valued function from Visual Basic.Net and how to store the result

In my VB.net code i have:
cmd.CommandText = "SELECT * FROM [strfg].[dbo].[Myfunc] (#MyParam)"
Dim myparam As New SqlParameter("#MyParam", a)
cmd.Parameters.Add(myparam)
The function (runnig on SQL server) returns a table with four columns, one row.
How do I call this function from Visual Basic? cmd.ExecuteScalar() is obviously not correct. In c++ I use a recordset. What is the equivalent in vb? Does anyone have a short example?
You want to do something like this:
Dim reader As SqlDataReader= cmd.ExecuteReader
Dim MyList as new List(Of WhateverObject)
Do While reader.Read
Dim obj as new WhateverObj
obj.Property1 = Reader.GetInt32(0)
obj.Property2 = Reader.GetString(1)
MyList.add(obj)
Loop
reader.Close()
cmd.Dispose()
Where you use the index value based on the order of the returned fields, and its type in the Get.
If you want something that is similar to a recordset consider using a datatable. Your code can look like:
Dim custId As String = "ALFKI"
Dim conn As New SqlConnection("Data Source=(local);Initial Catalog=Northwind;Integrated Security=True")
Dim da As New SqlDataAdapter("SELECT * FROM Customers Where CustomerId=#CustomerId", conn)
da.SelectCommand.Parameters.AddWithValue("#CustomerId", custId)
Dim ds As DataSet = New DataSet
da.Fill(ds)
Dim dt As DataTable = ds.Tables(0)
The datatable has a collection of Rows which contains your data.

Resources