VB.Net fires error on saving data to SQL Server - sql-server

I am creating a LMS in VB.Net and SQL Server. The book adding form contains text boxes combo boxes and picture box. When I click the save button It says the following error message
Conversion failed when converting the varchar value 'Saman' to data type int.
On the form load the combo boxes populate the data from the entire tables.
Tables and relationship
Data to be inserted
Tables with data type
Error message on saving
I tried with the following coding
Form load coding
Private Sub frmAddBook_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'To load Author details
Using com As New SqlCommand("SELECT * FROM tblBookAuthor", con)
Dim dt As New DataTable()
dt.Load(com.ExecuteReader)
cmbAuthor.DataSource = dt
cmbAuthor.DisplayMember = "authorFirstName"
cmbAuthor.ValueMember = "authorFirstName"
' con.Close()
End Using
'To load Publisher details
Using com2 As New SqlCommand("SELECT * FROM tblPublisher", con)
Dim dt As New DataTable()
dt.Load(com2.ExecuteReader)
cmbPub.DataSource = dt
cmbPub.DisplayMember = "publisherName"
cmbPub.ValueMember = "publisherName"
' con.Close()
End Using
'To load Class details
Using com3 As New SqlCommand("SELECT * FROM tblBookClass", con)
Dim dt As New DataTable()
dt.Load(com3.ExecuteReader)
cmbClass.DataSource = dt
cmbClass.DisplayMember = "classDetail"
cmbClass.ValueMember = "classDetail"
' con.Close()
End Using
'To load bookshelf details
Using com4 As New SqlCommand("SELECT * FROM tblBookShelfDetail", con)
Dim dt As New DataTable()
dt.Load(com4.ExecuteReader)
cmbBookShelf.DataSource = dt
cmbBookShelf.DisplayMember = "shelfDetail"
cmbBookShelf.ValueMember = "shelfDetail"
con.Close()
End Using
End Sub
Save button coding
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
sql = "INSERT INTO tblBookDetail (accessionNo, authorId, title, pages, price, ISBN, noOfCopies, pubId, classId, source, bookShelfNo,bookEdition, bookCoverImg) VALUES (#accNo, #auID, #title, #pages, #price, #ISBN, #noOfCopies, #pubID, #classID, #src, #shlfNo, #edition, #img)"
Dim ms As New MemoryStream()
picPhoto.Image.Save(ms, picPhoto.Image.RawFormat)
con.Open()
cmd = New SqlCommand(sql, con)
cmd.Parameters.Add("#accNo", SqlDbType.Int).Value = txtBookID.Text
cmd.Parameters.Add("#auID", SqlDbType.VarChar).Value = cmbAuthor.Text
cmd.Parameters.Add("#title", SqlDbType.VarChar).Value = txtEdition.Text
cmd.Parameters.Add("#pages", SqlDbType.Int).Value = txtPageNo.Text
cmd.Parameters.Add("#price", SqlDbType.Decimal).Value = txtPrice.Text
cmd.Parameters.Add("#ISBN", SqlDbType.Int).Value = txtISBN.Text
cmd.Parameters.Add("#noOfCopies", SqlDbType.Int).Value = txtNoOfCopies.Text
cmd.Parameters.Add("#pubID", SqlDbType.VarChar).Value = cmbPub.Text
cmd.Parameters.Add("#classID", SqlDbType.VarChar).Value = cmbClass.Text
cmd.Parameters.Add("#src", SqlDbType.VarChar).Value = cmbSrc.Text
cmd.Parameters.Add("#shlfNo", SqlDbType.VarChar).Value = cmbBookShelf.Text
cmd.Parameters.Add("#edition", SqlDbType.Int).Value = txtEdition.Text
cmd.Parameters.Add("#img", SqlDbType.Image).Value = ms.ToArray
cmd.ExecuteNonQuery()
MsgBox("SUCCESS")
con.Close()
End Sub

Program Error :
Conversion failed when converting the varchar value 'Saman' to data
type int.
Here, you are having column authorID as datatype integer, then how come you will be able to insert varchar, i.e Name 'Saman' into it !
Line of Code that trigger this error :
cmd.Parameters.Add("#auID", SqlDbType.VarChar).Value = cmbAuthor.Text
Make sure table column is not integer or change accordingly.
Edit :
If want to insert id then :
replace text with SelectedValue in combobox
Hope you got the point. Thanks

Related

How to pass dynamic parameter from SQL query to the SqlCommand after user input on the SQL query

all. I am facing an issue on how to pass the dynamic parameter value from SQL query, that will be entered by the user into the textbox, to the SQL command to search on the parameter value on the datagridview datatable.
For my project, a textbox will be provided for the user to key in the SQL query dynamically to search on the database data. If the user keys in SQL query like
select *
from table
where a = #a
The user can search on #a parameter value; if the user keys in SQL query like
select *
from table
where a = #a and b = #b
The user can search the #a and #b parameter values by using textbox, which means that the parameter number that had been entered by the user needs to be calculated, retrieved, passed to the SQL command and allow the user to filter on the parameter by using textbox provided.
However, currently, due to the #a parameter and #b parameter will be key in by the user dynamically during runtime, so I faced difficulty to declare/define the parameter name on the cmd.Parameters.AddWithValue() statement.
Can anyone help me to solve my problem by providing me some solutions on codes? I had been stuck on this issue for a few days already. Thank you for all the help!
The code I had tried:
Private Sub btn1_Click(sender As Object, e As EventArgs) Handles btn1.Click
Sql = TextBox4.Text
Try
'open database
Dim con As New SqlConnection(dbstring)
con.Open()
Dim cmd As New SqlCommand(Sql, con)
If param IsNot Nothing Then
For Each para As SqlParameter In param
'cmd.Parameters.Add(para)
For m As Integer = 0 To param.Count - 1
cmd.Parameters.Add(New SqlParameter With {.ParameterName = para.ParameterName(m),
.Value = para.Value(m),
.SqlDbType = SqlDbType.NVarChar,
.Size = 99})
Next
cmd.ExecuteNonQuery()
Next
End If
Using sda = New SqlDataAdapter()
sda.SelectCommand = cmd
cmd.CommandText = Sql
Sql = cmd.ExecuteScalar()
Using ds As DataSet = New DataSet()
sda.Fill(ds)
con.Close()
DataGridView1.DataSource = ds.Tables(0)
End Using
End Using
con.Close()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Screenshot of Window App Formhad been provided as a reference.
To avoid SQL Injection, im usally doing like this:
Dim text1 As String = "text1"
Dim objComm As SqlCommand = New SqlCommand
objComm.Parameters.AddWithValue("#text1", text1)
objComm.CommandText = "SELECT * FROM TABLE WHERE Text1 = #text1"
I am not sure why you would want the user to write Select statements. I assume this query is on a single table where you know the field names, types and field sizes where applicable. I made up the these items. You will have to check your database to get the correct information.
I used Optional parameters in case you have other datatypes like Booleans or numbers where you can supply the defaults. To pass no value for the parameter just leave a blank but insert the appropriate commans.
Private Function GetSearchResults(Optional FirstName As String = "", Optional LastName As String = "") As DataTable
Dim dt As New DataTable
Using con As New SqlConnection(dbstring),
cmd As New SqlCommand()
Dim sb As New StringBuilder
sb.Append("Select * From SomeTable Where 1 = 1")
If FirstName <> "" Then
cmd.Parameters.Add("#a", SqlDbType.NVarChar, 100).Value = FirstName
sb.Append(" And FirstName = #a")
End If
If LastName <> "" Then
cmd.Parameters.Add("#b", SqlDbType.NVarChar, 100).Value = LastName
sb.Append(" And LastName = #b ")
End If
sb.Append(";")
Debug.Print(sb.ToString)
cmd.CommandText = sb.ToString
cmd.Connection = con
con.Open()
dt.Load(cmd.ExecuteReader)
End Using
Return dt
End Function
Alternative useage:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim dt = GetSearchResults(TextBox1.Text, TextBox2.Text)
DataGridView1.DataSource = dt
End Sub
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim dt = GetSearchResults(, TextBox2.Text)
DataGridView1.DataSource = dt
End Sub
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
Dim dt = GetSearchResults(TextBox1.Text, )
DataGridView1.DataSource = dt
End Sub

How to detect it was duplicate entry on VB.NET?

I have a problem on making avoid or detect duplicate data entry in VB.NET using SQL Server, and also pop up message when there is duplicate entry.
This is my add button code:
Dim sql = "INSERT INTO studentAttendence(studentID, date, time, subject, attendence) " &
"VALUES(#studentID, #date, #time, #subject, #attendence)" &
"WHERE NOT EXISTS(SELECT * FROM studentAttendence WHERE studentID = #studentID)"
Using cn As New SqlConnection("My sql Connection string")
Dim commands As SqlCommand = New SqlCommand(sql, cn)
commands.Parameters.Add("#studentID", SqlDbType.NVarChar).Value = TextBox1.Text
commands.Parameters.Add("#date", SqlDbType.NVarChar).Value = DateTimePicker1.Text
commands.Parameters.Add("#time", SqlDbType.NVarChar).Value = DateTimePicker2.Text
commands.Parameters.Add("#subject", SqlDbType.NVarChar).Value = ComboBox1.Text
commands.Parameters.Add("#attendence", SqlDbType.NVarChar).Value = ComboBox2.Text
commands.ExecuteNonQuery()
End Using
Or is there any other methods for making avoid duplicate entries. I just want to avoid same date and subject of a student to add. So I can only add subject on the next date if I already add subject on today's date of studentID.
You can use If Not Exists before the insert. This method only requires a single hit on the database. Add a comman at the end of the first line of the Using block, then delete Dim before commands. This will include commands in the Using block.
Private Function InsertAttendance() As Integer
Dim sql = "If Not Exists (Select 1 From studentAttendence
Where studnetID = #studentID And date = #date And subject = #subject)
INSERT INTO studentAttendence(studentID, date, time, subject, attendence)
VALUES(#studentID, #date, #time, #subject, #attendence);"
Dim NumRowsAffected As Integer
Using cn As New SqlConnection("My sql Connection string"),
commands As SqlCommand = New SqlCommand(sql, cn)
commands.Parameters.Add("#studentID", SqlDbType.NVarChar).Value = TextBox1.Text
commands.Parameters.Add("#date", SqlDbType.NVarChar).Value = DateTimePicker1.Text
commands.Parameters.Add("#time", SqlDbType.NVarChar).Value = DateTimePicker2.Text
commands.Parameters.Add("#subject", SqlDbType.NVarChar).Value = ComboBox1.Text
commands.Parameters.Add("#attendence", SqlDbType.NVarChar).Value = ComboBox2.Text
cn.Open()
NumRowsAffected = commands.ExecuteNonQuery()
End Using
Return NumRowsAffected
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try
If InsertAttendance() = 1 Then
MessageBox.Show("Success")
Else
MessageBox.Show("Duplicate Entry")
End If
Catch ex As Exception
MessageBox.Show($"Error Entering Attendance {ex.Message}")
End Try
End Sub
Be sure to check the datatypes of your parameters with the database.
You should create a function that queries your data table to return the row count where the Date, Subject, and StudentId match what you're wanting to insert. If the returned result is greater than 0 then display the message.
Here is a function that returns -1 if something went wrong or the row count:
Private Function GetRowCount(ByVal studentIdParameter As String, ByVal dateParameter As DateTime, ByVal subjectParameter As String) As Integer
'Declare the object to return
Dim count As Integer = -1
'Declare the connection object
Dim con As OleDbConnection
'Wrap code in Try/Catch
Try
'Set the connection object to a new instance
'TODO: Change "My Connection String Here" with a valid connection string
con = New OleDbConnection("My Connection String Here")
'Create a new instance of the command object
'TODO: Change [ID] to a valid column
Using cmd As OleDbCommand = New OleDbCommand("SELECT Count([ID]) FROM [MyTable] WHERE studentID=#studentId, AND date=#date AND subject=#subject", con)
'Parameterize the query
cmd.Parameters.Add("#studentId", OleDbType.NVarChar).Value = studentIdParameter
cmd.Parameters.Add("#date", OleDbType.DBDate).Value = dateParameter.Date
cmd.Parameters.Add("#subject", OleDbType.NVarChar).Value = subjectParameter
'Open the connection
con.Open()
'Use ExecuteScalar to return a single value
count = Convert.ToInt32(cmd.ExecuteScalar())
'Close the connection
con.Close()
End Using
Catch ex As Exception
'Display the error
Console.WriteLine(ex.Message)
Finally
'Check if the connection object was initialized
If con IsNot Nothing Then
If con.State = ConnectionState.Open Then
'Close the connection if it was left open(exception thrown)
con.Close()
End If
'Dispose of the connection object
con.Dispose()
End If
End Try
'Return the row count
Return count
End Function
To implement it, you'd do something like:
Dim rowCount = GetRowCount(TextBox1.Text, DateTimePicker1.Value, ComboBox1.Text)
If (rowCount = -1) Then
MessageBox.Show("Something went wrong checking for duplicates")
ElseIf (rowCount = 0) Then
' Insert record
Else
MessageBox.Show("A record already exists with this studentId, date, and subject.")
End If

Operand type clash: date is incompatible with int

I have difficulty with the following code. I think it lies in my sql statement.
I get the error :
Operand type clash: date is incompatible with int
Dim strSql5 As String = "SELECT * FROM dbo.ontledings where plaasblok = '" & plaasblokparsversoeke & "' and analisedatum = " & laastedatum.Date
MsgBox(strSql5)
Dim dtb5 As New DataTable
dtb5.Clear()
Using cnn As New SqlConnection("Data Source=GIDEON-E-LAPTOP\SQLEXPRESS2014;Initial Catalog=SkeduleringDatabasis;Integrated Security=True")
cnn.Open()
Using dad5 As New SqlDataAdapter(strSql5, cnn)
dad5.Fill(dtb5)
End Using
cnn.Close()
End Using
Dim laasteontleding As Decimal = dtb5.Rows(0)("suiker")
I get the laastedatum from the following code :
Dim laastedatum As Date = dtb4.Rows(0)("last")
Any help would be much appreciated.
Regards
Do not use SELECT *, use SELECT field list. Then use Field(Of T) to get the date information strongly typed. Always used Option Strict On.
Example reading order data from Microsoft NorthWind database orders table, note the field retrieval.
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim EmployeeId As Integer = 2
Dim dt As New DataTable
Using cn As New SqlClient.SqlConnection With {.ConnectionString = My.Settings.ConnectionString}
Using cmd As New SqlClient.SqlCommand With {.Connection = cn}
cmd.CommandText =
<SQL>
SELECT [OrderID]
,[CustomerID]
,[EmployeeID]
,[OrderDate]
,[ShipCountry]
FROM [NORTHWND.MDF].[dbo].[Orders]
WHERE [EmployeeID] = #EmployeeID
ORDER BY CustomerId
</SQL>.Value
cmd.Parameters.AddWithValue("#EmployeeID", EmployeeId)
cn.Open()
dt.Load(cmd.ExecuteReader)
For Each row As DataRow In dt.Rows
Console.WriteLine("id: {1} date: {0}",
row.Field(Of Date)("OrderDate").ToShortDateString,
row.Field(Of String)("CustomerId"))
Next
End Using
End Using
End Sub
End Class
Get first date
Dim rowOneOrderDate As Date = dt.Rows(0).Field(Of Date)("ORderDate")

Microsoft SQL Server SELECT statement

I need help retrieving ReceiptNO column from a database table and saving it into a TextBox or Label for referencing.
CODE:
Dim da2 As New SqlDataAdapter
da2.SelectCommand = New SqlCommand("SELECT RecepitNO FROM Receipt WHERE (PaidFor=#PaidFor AND RegNO=#RegNO)")
da2.SelectCommand.Parameters.Add("#paidFor", SqlDbType.VarChar).Value = cbMonth.Text
da2.SelectCommand.Parameters.Add("#RegNO", SqlDbType.Int).Value = lblRegNO.Text
cn.Open()
da2.Update(ds.Tables("Receipt"))
'da2.SelectCommand.ExecuteNonQuery()
da2.SelectCommand.ExecuteReader()
cn.Close()
You need to use a SqlDataReader, and then start a loop to read the values returned
This example will work assuming the ReceiptNO is a text field
cn.Open()
Dim reader = da2.SelectCommand.ExecuteReader()
while reader.Read()
textBox1.Text = reader("ReceiptNO").ToString()
End While
In alternative, if you are sure that your query returns zero or just one record and you are interested only in the ReceiptNO field, then you can use ExecuteScalar
Dim cmd = New SqlCommand("SELECT RecepitNO FROM Receipt WHERE (PaidFor=#PaidFor AND RegNO=#RegNO)")
cmd.Connection = cn
cmd.Parameters.Add("#paidFor", SqlDbType.VarChar).Value = cbMonth.Text
cmd.Parameters.Add("#RegNO", SqlDbType.Int).Value = lblRegNO.Text
cn.Open()
Dim result = cmd.ExecuteScalar()
if result IsNot Nothing Then
textBox1.Text = result.ToString()
End If
Here the MSDN docs on ExecuteScalar

delete selected row from gridview and and update databse in vb.net windows form

I have a Delete button and i am trying to delete selected rows from gridview and database by clicking on that button. but having following code i am getting error like Argument out of range and convert to int.
Private Sub dltButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles dltButton.Click
'Dim StudentId As String
'StudentId =
'con.Open()
'cmd.CommandText = "delete from KaiyumVbStudent where StudentID = '"&StudentId&"'"
'cmd.Connection = con
Dim i As Integer = DataGridView1.SelectedRows(0).Index
DataGridView1.Rows.Remove(DataGridView1.SelectedRows(0))
con = New SqlConnection(constring)
con.Open()
Me.StudentID = Convert.ToInt32(DataGridView1.SelectedRows(0).Index)
cmd = New SqlCommand("Delete from KaiyumVbStudent where StudentID = '#StudentID'", con)
cmd.ExecuteNonQuery()
Call databind()
Private Sub databind()
con = New SqlConnection(constring)
con.Open()
cmd = New SqlCommand("Select *from KaiyumVbStudent", con)
Dim dr As SqlDataReader = cmd.ExecuteReader()
dt = New DataTable()
dt.Load(dr)
Me.DataGridView1.DataSource = dt
End Sub
First put our code in try catch statement and check student Id datatype
Your are missing one statement
cmd.Parameters.AddWithValue("#StudentID", StudentID);
I hope you it is work..

Resources