I have the following code. My problem is I can't insert a record in my table and when I run the code there is no error. What is wrong with the code?
Dim Conn As SqlConnection
Dim cmd As SqlCommand
Dim ConString As String
ConString = "SERVER=MAXPAYNE-PC\DEVELOPER;DATABASE=sample;User=sa;Pwd=bwd"
Conn = New SqlConnection(ConString)
Try
Conn.Open()
For J As Integer = 0 To ListBox3.Items.Count - 1
cmd = New SqlCommand("INSERT INTO players (name) VALUES (" & ListBox3.Items(J).ToString & ")")
cmd.ExecuteNonQuery()
Next
Conn.Close()
Catch ex As Exception
End Try
"when I run the code there is no error" there's no error because you have an empty catch. Why are empty catch blocks a bad idea?
The error is that the command has no connection assigned. This should work:
cmd = New SqlCommand("INSERT INTO players (name) VALUES (" & ListBox3.Items(J).ToString & ")")
cmd.Connection = Conn
You should also get familiar with the Using-statement and use that on all objects that implement IDisposable like SqlConnection which ensures that it gets dispoed/closed always(even on error).
Last but not least: always use SQL-Parameters instead of string concatenation to prevent sql-injection:
Using conn As New SqlConnection("SERVER=MAXPAYNE-PC\DEVELOPER;DATABASE=sample;User=sa;Pwd=bwd")
Dim sql = "INSERT INTO players (name) VALUES (#name)"
Using cmd As New SqlCommand(sql, conn)
Dim nameParameter = New SqlParameter("#name", SqlDbType.NVarChar)
cmd.Parameters.Add(nameParameter)
conn.Open()
For Each name As String In ListBox3.Items
cmd.Parameters("#name").Value = name
Try
Dim inserted As Int32 = cmd.ExecuteNonQuery()
Catch ex As Exception
' do something meaningful here (f.e. logging or at least output the error) '
' empty catches are evil in most cases since they conceal problems from you but not from the users '
Throw
End Try
Next
End Using
End Using ' conn.Close not needed due to the Using '
Related
I get this error when I run the code. The records are inserted into the table, but the program stops at the error.
The parameterized query '(#EmpName varchar(8000),#USDBasic varchar(8000),#OtherUSDEarning' expects the parameter '#EmpName', which was not supplied.
Code:
Dim connetionString As String
Dim cnn As SqlConnection
connetionString = "Data Source=Server\SQlExpress;Initial Catalog=CreSolDemo;User ID=sa;Password=Mkwn#011255"
cnn = New SqlConnection(connetionString)
If DataGridView1.Rows.Count > 0 Then
Dim cmd As New Data.SqlClient.SqlCommand
cmd.CommandText = " INSERT INTO TempPeriodTrans (EmpName, USDBasic, OtherUSDEarnings, ZDollarBasic, OtherZDEarnings) VALUES (#EmpName, #USDBasic, #otherUSDEarnings, #ZDollarBasic, #OtherZDEarnings) "
cmd.Parameters.Add("#EmpName", SqlDbType.VarChar)
cmd.Parameters.Add("#USDBasic", SqlDbType.VarChar)
cmd.Parameters.Add("#OtherUSDEarnings", SqlDbType.VarChar)
cmd.Parameters.Add("#ZDollarBasic", SqlDbType.VarChar)
cmd.Parameters.Add("#OtherZDEarnings", SqlDbType.VarChar)
cmd.Connection = cnn
cnn.Open()
For i As Integer = 0 To DataGridView1.Rows.Count - 1
cmd.Parameters(0).Value = DataGridView1.Rows(i).Cells(0).Value
cmd.Parameters(1).Value = DataGridView1.Rows(i).Cells(1).Value
cmd.Parameters(2).Value = DataGridView1.Rows(i).Cells(2).Value
cmd.Parameters(3).Value = DataGridView1.Rows(i).Cells(3).Value
cmd.Parameters(4).Value = DataGridView1.Rows(i).Cells(4).Value
cmd.ExecuteNonQuery()
Next
cnn.Close()
End If
MsgBox("Record saved")
End Sub
There seem to be a few things here.
As a rule, any time you open a connection to your data base it should be wrapped in a Using block so that that connection gets closed and disposed before you exit that block
You have a lot of params that are being set as SqlDbType.varchar where you should probably have other types. (SqlDbType.Money in particular)
When you are working with sqlcommand, it is worth wrapping it in a using block as well and creating a new one as you need it.
There is some memory to it where it will try not to reuse parameters in subsequent queries. Instead of just changing the value of the param, throw that sqlCommand in the trash bin each time and grab a new one. This is where I believe your problem is. I moved the sqlcommand creation into your loop and declare the values in-line below.
Also, protip, avoid including your actual password in the connetion string on Stack Overflow
Dim connectionString As String = "yourConnectionString"
Using cnn As new SqlConnection(connectionString)
cnn.Open()
For Each row in DataGridView1.Rows
Using cmd As New Data.SqlClient.SqlCommand("INSERT INTO TempPeriodTrans (EmpName, USDBasic, OtherUSDEarnings, ZDollarBasic, OtherZDEarnings) Values (#EmpName, #USDBasic, #otherUSDEarnings, #ZDollarBasic, #OtherZDEarnings) ", cnn)
cmd.Parameters.Add("#EmpName", SqlDbType.VarChar).value = row.Cells(0).Value
cmd.Parameters.Add("#USDBasic", SqlDbType.VarChar).value = row.Cells(1).Value
cmd.Parameters.Add("#OtherUSDEarnings", SqlDbType.VarChar).value = row.Cells(2).Value
cmd.Parameters.Add("#ZDollarBasic", SqlDbType.VarChar).value = row.Cells(3).Value
cmd.Parameters.Add("#OtherZDEarnings", SqlDbType.VarChar).value = row.Cells(4).Value
cmd.ExecuteNonQuery()
End using
Next
End using
MsgBox("Record Saved")
End Sub
I've been trying to insert data into my sql database but this problem always show up
i've tried redoing it again and the same problem occurs and i'm really stumped right now
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim conn As SqlConnection = New SqlConnection("Data Source=DESKTOP-OBQR58O\SQLEXPRESS;Initial Catalog=Accounts;Integrated Security=True")
Dim comm As SqlCommand = New SqlCommand("insert into User(username, password)values('" + TextBox1.Text + "', '" + TextBox3.Text + "')", conn)
Dim data As SqlDataAdapter = New SqlDataAdapter(comm)
Dim user = TextBox1.Text
Dim pass = TextBox2.Text
Dim cpass = TextBox3.Text
Dim reader As SqlDataReader
conn.Open()
Dim cmd As SqlCommand = New SqlCommand("select Username from [User] where Username ='" + TextBox1.Text + "'", conn)
conn.Close()
conn.Open()
reader = cmd.ExecuteReader
If user.Trim() = "" Or pass.Trim() = "" Or cpass.Trim() = "" Then
MessageBox.Show("Empty Fields", "Blank Spaces")
ElseIf Not String.Equals(pass, cpass) Then
MessageBox.Show("Passwords do not match", "ERROR")
conn.Close()
ElseIf reader.HasRows Then
MessageBox.Show("Username already exists!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning)
TextBox1.Clear()
conn.Close()
reader.Close()
Else
MessageBox.Show("Account created succesfully!", "Success")
Dim table As DataTable = New DataTable()
data.Fill(table) ' this is where the problem occurs.
TextBox1.Clear()
TextBox2.Clear()
TextBox3.Clear()
Dim log As New Login
Me.Close()
log.Show()
conn.Close()
End If
conn.Close()
End Sub
I honestly don't know what to do
You open your reader up at the top:
reader = cmd.ExecuteReader
So, it's open. And then, when you run the Fill command, it conflicts with the open reader!
The simplest fix - although, personally, I would restructure the code a bit, to bring the OpenReader nearer to where it is used - would be to add a Close to your reader right before the Fill.
Else
reader.Close() ' what you would add
MessageBox.Show("Account created succesfully!", "Success")
Dim table As DataTable = New DataTable()
data.Fill(table) ' this is where the problem occurs.
VERY IMPORTANT: If you're not familiar with the concept of "SQL Injection Attacks", read up on them, right away. You should NEVER execute SQL that's been built by constructing a string with unvalidated data from the user. You should pass parameters instead.
After all, what if I typed in the user name of "Irrelevant';DROP TABLE Users;--"? You'd wind up with a SQL Statement that contained "SELECT Username from [Users] WHERE [Username] = 'Irrelevant'; DROP TABLE Users; --'"
And, of course, you should validate the input as well, for things like embedded HTML and script! But that's more complicated than just using SQL Parameters.
In the Database, I used an assigned ProgName = varchar,MaleCuteOff = int,FemaleCutOff=int, and I'm trying to collect User input for the values, but I'm getting an Error
Conversion from string "INSERT INTO CutOff_Point((ProgN" to type
integer is not valid.
Sub save()
Dim query As String = "INSERT INTO CutOff_Point (ProgName, MaleCutOff, FemaleCutOff) VALUES (#colProg, #colMale, #colFemale)"
Using con As New SqlConnection("Data Source=.;Initial Catalog=UEW_ADMISSION_CHEAKER;Integrated Security=True")
Using com As New SqlCommand()
With com
.Connection = con
.CommandType = query
.Parameters.AddWithValue("#colProg", cmbProg.SelectedItem.ToString)
.Parameters.AddWithValue("#colMale", txtMaleCut.Text.ToString)
.Parameters.AddWithValue("#colFemale", txtFemaleCut.Text.ToString)
End With
Try
con.Open()
com.ExecuteNonQuery()
Catch ex As SqlException
MessageBox.Show(ex.Message.ToString(), "Saving data Not Complete")
End Try
End Using
End Using
End Sub
This:
.CommandType = query
should be setting Commandtext, not CommandType. Why set those properties like that in the first place, when you can use the constructor?
Using com As New SqlCommand(query, con)
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
I am reading data from an sql database and the connection happens but the following error occurs:
{"Index was outside the bounds of the array."}
On this line:
TextBox2.Text = TextBox2.Text & sqRdr.GetValue(22) & vbCrLf
Please help me with this as I have counted all the columns in my table and they have turned out to be exactly (22).
The column ordinal for the datareader is 0 based, so the 22nd column would be sqRdr.GetValue(21)
Your Datareader should be like below to avoid this issue in a case when you have increased/decreased the number of column in future....
DR["ColumnName"]
SqlDataReader's this[string name] looks like:
Public Overrides Default ReadOnly Property Item(name As String) As Object
Get
Return Me.GetValue(Me.GetOrdinal(name))
End Get
End Property
Below is the sample code...
Using con As System.Data.SqlClient.SqlConnection = New SqlConnection("YourConnection string")
con.Open()
Dim cmd As New SqlCommand()
Dim expression As String = "Parameter value"
cmd.CommandType = CommandType.StoredProcedure
cmd.CommandText = "Your Stored Procedure"
cmd.Parameters.Add("Your Parameter Name", SqlDbType.VarChar).Value = expression
cmd.Connection = con
Using dr As IDataReader = cmd.ExecuteReader()
'You code like ....dr["YourColumnName"]
If dr.Read() Then
End If
End Using
End Using