I have the below snippet of code whenever I try registering the username exist part seems to be executed even for a username that doesn't exist in the database. Don't know where am wrong here any help will be appreciated.
'Connecting to SQL Database and executing Query------------------------------------------
Dim Strconn As String = "Data Source=.\SQLEXPRESS; Database=QuizDB; Integrated Security = true"
Dim Strcmd As String = "INSERT INTO reg_info(uname,pass,fname,lname,dob,course,college) VALUES ('" & user_name.Text & "','" & con_pass.Text & "', '" & first_name.Text & "', '" & last_name.Text & "', '" & dob.Text & "', '" & course.Text & "', '" & college.Text & "');"
Dim da As New SqlDataAdapter
Dim ds As New DataSet
Dim sqlcmd As SqlCommand
sqlconn = New SqlConnection(Strconn)
Try
sqlconn.Open()
Catch ex As Exception
MsgBox("Could not connect to DataBase. Application will close now!", vbCritical, "Database Error")
End
End Try
sqlcmd = New SqlCommand(Strcmd, sqlconn)
da.SelectCommand = sqlcmd
sqlcmd.Dispose()
sqlconn.Close()
'Exception Handling-----------------------
Dim exc As Exception = Nothing
Try
da.Fill(ds)
Catch ex As Exception
exc = ex
Finally
If Not (exc) Is Nothing Then
MsgBox("User Name Already Exist. Please select a different User Name!", vbExclamation, "Already Exist")
user_name.Focus()
Else
MsgBox("Registration Successful.", vbInformation, "Successful")
Me.Close()
Login.Show()
End If
End Try
Here is a refactor of your code with some helpful guidance. I think this will compile, but if it does not, then you can do a little homework to figure out what is missing.
Try
' the USING block guarantees that the object's Close() and Dispose() methods are fired automatically when you exit the block
Using sqlconn As New SqlConnection("Data Source=.\SQLEXPRESS; Database=QuizDB; Integrated Security = true")
Using sqlcmd As SqlCommand = sqlconn.CreateCommand
With sqlcmd
.CommandType = CommandType.Text
' parameterized query to protect against SQL injection
.CommandText = "INSERT INTO reg_info(uname,pass,fname,lname,dob,course,college) VALUES (#username, #password, #firstname, #lastname, #dob, #course, #college)"
With .Parameters
.Clear()
.AddWithValue("#username", user_name.Text)
.AddWithValue("#password", con_pass.Text)
.AddWithValue("#firstname", first_name.Text)
.AddWithValue("#lastname", last_name.Text)
.AddWithValue("#dob", dob.Text)
.AddWithValue("#course", course.Text)
.AddWithValue("#college", college.Text)
End With
.ExecuteScalar() ' Actually executes the SQL command
End With
End Using
End Using
MsgBox("Registration successful")
Catch ex As Exception
' Any error in the TRY block will automatically jump to herem and the "ex" object will be an Exception object with populated properties
MsgBox("User name already exists. Error from database is " & ex.Message)
End Try
Related
This problem at syntax error for update statement then I don't know how to solve this problem
Private Sub editStaff()
Try
If con.State = ConnectionState.Closed Then
con.Open()
End If
If IDTextBox.Text <> "" And FirstTextBox.Text <> "" And SecondTextBox.Text <> "" And UsernameTextBox.Text <> "" And PasswordTextBox.Text <> "" Then
strSQL = "update Staff set First_Name = '" & FirstTextBox.Text & "', " &
"Second_Name = '" & SecondTextBox.Text & "', " & "Username = '" & UsernameTextBox.Text & "', " &
"Password = '" & PasswordTextBox.Text & "'" & " where ID = " & CInt(IDTextBox.Text) & ""
Dim cmd As OleDbCommand = New OleDbCommand(strSQL, con)
Try
cmd.ExecuteNonQuery()
cmd.Dispose()
con.Close()
MessageBox.Show("Update Successful")
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End If
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
End Sub
For some reason your validation If did not include the ID text box. I added validation for this text box. The OrElse is a short circuit. As soon as it finds a True it stops checking the conditions and proceeds to the next line.
This code
If con.State = ConnectionState.Closed Then
con.Open()
End If
is completely unnecessary if you keep your database objects local. Keeping them local allows you to ensure they are closed and disposed with Using...End Using blocks.
Don't open the connection until you need it which is directly before the .Execute... line. Use parameters to avoid Sql Injection. Also your Update statement is much easier to write without all the single quotes and double quotes and ampersands.
Caution In Access the order that the parameters appear in the Sql statement must match the order that they are added to the .Parameters collection.
Finally, you should NEVER store passwords as plain text. I will leave it to you to research salting and hashing and correct the code.
Private Sub editStaff()
Dim i As Integer
If Integer.TryParse(IDTextBox.Text, i) Then
MessageBox.Show("ID text box must be a number")
Return
End If
If IDTextBox.Text = "" OrElse FirstTextBox.Text = "" OrElse SecondTextBox.Text = "" OrElse UsernameTextBox.Text = "" OrElse PasswordTextBox.Text = "" Then
MessageBox.Show("Please fill in all text boxes")
Return
End If
Try
Using con As New OleDbConnection("Your connection string")
Dim strSQL = "Update Staff set First_Name = #FirstName, Second_Name = #SecondName, [Username] = #UserName, [Password] = #Password Where [ID] = #ID"
Using cmd As New OleDbCommand(strSQL, con)
With cmd.Parameters
.Add("#FirstName", OleDbType.VarChar).Value = FirstTextBox.Text
.Add("#SecondName", OleDbType.VarChar).Value = SecondTextBox.Text
.Add("#UserName", OleDbType.VarChar).Value = UsernameBox.Text
.Add("#Password", OleDbType.VarChar).Value = PasswordTextBox.Text
.Add("#ID", OleDbType.Integer).Value = CInt(IDTextBox.Text)
End With
con.Open()
cmd.ExecuteNonQuery()
End Using
End Using
MessageBox.Show("Update Successful")
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
End Sub
invalid attempt to read when reader is closed error. vb.net
I have the code below that I use to login into MySQL but it keeps displaying the error 'invalid attempt to read when reader is closed' and then it logs in. I don't understand what could still be wrong with the code. Kindly assist, it's so frustrating. Thanks.
Try
ConnDB()
command = con.CreateCommand()
command.CommandText = "SELECT UserName,Password,Type,EmpNo FROM userstable where UserName=#d1 and Password=#d2 and Active='Yes'"
command.Parameters.AddWithValue("#d1", txtUsername.Text)
command.Parameters.AddWithValue("#d2", txtPassword.Text)
Reader = command.ExecuteReader()
If Reader.Read = True Then
ComboBox1.Text = Reader.GetValue(2)
lblUser.Text = Reader.GetValue(3)
End If
If (Reader IsNot Nothing) Then
Reader.Close()
End If
If con.State = ConnectionState.Open Then
con.Close()
End If
If ComboBox1.Text.Length > 0 Then
MainMenu.lblUserName.Text = Me.txtUsername.Text
MainMenu.lblType.Text = Me.ComboBox1.Text
MainMenu.lblOccupation.Text = Me.ComboBox1.Text
MainMenu.lblUser.Text = Me.lblUser.Text
Dim st As String = "Successfully logged in"
LogFunc(txtUsername.Text, st)
Me.Hide()
MainMenu.Show()
Else
MsgBox("Incorrect username or password..Login is Failed...Try again !", MsgBoxStyle.Critical, "Login")
txtUsername.SelectAll()
txtPassword.SelectAll()
txtUsername.Focus()
txtPassword.Text = ""
End If
command.Dispose()
' Reader.Close()
'command.Dispose()
con.Close()
Catch ex As Exception
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Finally
DisconnMy()
End Try
I expect it to log in successfully without displaying the error.
Sorry, I forgot to add this for my connection string.
Public Sub ConnDB()
con.Close()
Try
con.ConnectionString = "Server = '" & ServerMySQL & "'; " _
& "Port = '" & PortMySQL & "'; " _
& "Database = '" & DBNameMySQL & "'; " _
& "user id = '" & UserNameMySQL & "'; " _
& "password = '" & PwdMySQL & "'"
con.Open()
Catch ex As Exception
MsgBox("The system failed to establish a connection", MsgBoxStyle.Information, "Database Settings")
End Try
End Sub
In general it's not a good idea to use a "global", single connection for everything. Note that connection-pooling is enabled by default which means that .NET will take care of the physical connections. So you should create,open,use and close/dispose the connection where you use it.
I'm pretty sure that this will fix the issue:
Try
Using con As New MySql.Data.MySqlClient.MySqlConnection(MySettings.Default.SqlConnection)
Using command = con.CreateCommand()
command.CommandText = "SELECT UserName,Password,Type,EmpNo FROM userstable where UserName=#d1 and Password=#d2 and Active='Yes'"
command.Parameters.AddWithValue("#d1", txtUsername.Text)
command.Parameters.AddWithValue("#d2", txtPassword.Text)
con.Open()
Using reader = command.ExecuteReader()
If reader.Read() Then
ComboBox1.Text = reader.GetValue(2)
lblUser.Text = reader.GetValue(3)
End If
' NOTE: you dont need to close the reader/command/connection
' if you use the Using-statement, it will use Dispose even in case of an error
End Using
End Using
End Using
Catch ex As Exception
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
When I try to insert data in these three field gets an error saying error in INSERT INTO Statement.
but when a save in only the first field sname it gets added but when adds other two gets this error
I am getting an exception in INSERT INTO Statement check below
any advice?
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Try
Dim dbprovider As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\Taher\Documents\Visual Studio 2010\Projects\WindowsApplication1\WindowsApplication1\Database1.accdb;Persist Security Info=False;"
Me.con = New OleDb.OleDbConnection()
con.ConnectionString = dbprovider
con.Open()
Dim sqlquery As String = "INSERT INTO admin (sname,username,password)" + "VALUES ('" & txtname.Text & "','" & txtuser.Text & "','" & txtpass.Text & "');"
Dim sqlcommand As New OleDb.OleDbCommand(sqlquery)
With sqlcommand
.CommandText = sqlquery
.Connection = con
.ExecuteNonQuery()
con.Close()
End With
MsgBox("User Registered")
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
The word PASSWORD is a reserved keyword in JET-SQL for Microsoft Access. If you have a column with that name you should encapsulate it with square brackets
"INSERT INTO admin (sname,username,[password])" &% _
"VALUES ('" & txtname.Text & "','" & txtuser.Text & _
"','" & txtpass.Text & "');"
That's the reason of the syntax error, however let me tell you that building sql commands concatenating strings is a very bad practice. You will have problems when your values contain single quotes and worst of all, your code could be used for sql injection Attacks
So your code should be changed in this way
Dim sqlquery As String = "INSERT INTO admin (sname,username,password)" & _
"VALUES (?, ?, ?)"
Dim sqlcommand As New OleDb.OleDbCommand(sqlquery)
With sqlcommand
.CommandText = sqlquery
.Connection = con
.Parameters.AddWithValue("#p1", txtname.Text)
.Parameters.AddWithValue("#p2", txtuser.Text)
.Parameters.AddWithValue("#p3", txtpass.Text)
.ExecuteNonQuery()
con.Close()
End With
also your use of the object OleDbConnection doesn't follow a good pattern. In case of exception you don't close the connection and this could be a problem in reusing the connection in subsequent calls.
You should try to use the Using statement
Using connection = New OleDb.OleDbConnection()
connection.ConnectionString = dbprovider
connection.Open()
.....
' rest of command code here '
' No need to close the connection
End Using
in this way, also if you get an exception the OleDbConnection will be closed and disposed without impact on system resource usage.
I've found some tutorials on this already, but they aren't exactly what I'm looking for, I can use the following for username fields and password fields
Private Sub UsernameTextBox_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles UsernameTextBox.KeyPress
If Char.IsDigit(e.KeyChar) OrElse Char.IsControl(e.KeyChar) OrElse Char.IsLetter(e.KeyChar) Then
e.Handled = False
Else
e.Handled = True
End If
End Sub
But for an email field how would I go about protecting against SQL injection for that textbox, as some email accounts have periods or dashes in them?
Update:
Below is an example of an insert statement I use.
Dim con As SqlConnection
con = New SqlConnection()
Dim cmd As New SqlCommand
Try
con.ConnectionString = "Data Source=" & Server & ";Initial Catalog=" & Database & ";User ID=" & User & ";Password=" & Password & ";"
con.Open()
cmd.Connection = con
cmd.CommandText = "INSERT INTO TB_User(STRUserID, password, Email) VALUES('" & UsernameTextBox.Text & "', '" & MD5Hash(PasswordTextBox.Text) & "', '" & EmailTextBox.Text & "')"
cmd.ExecuteNonQuery()
Catch ex As Exception
MessageBox.Show("Error while inserting record on table..." & ex.Message, "Insert Records")
Finally
con.Close()
End Try
So I need to run this with parametrized queries rather than how I'm doing it now?
Instead of filtering out "invalid" data from user input, consider using parametrized queries and not putting user input directly into your queries; that's very bad form.
To run your current query using parameters, it's pretty easy:
Dim con As New SqlConnection()
Dim cmd As New SqlCommand()
Try
con.ConnectionString = "Data Source=" & Server & ";Initial Catalog=" & Database & ";User ID=" & User & ";Password=" & Password & ";"
con.Open()
cmd.Connection = con
cmd.CommandText = "INSERT INTO TB_User(STRUserID, password, Email) VALUES(#username, #password, #email)"
cmd.Parameters.Add("#username", SqlDbType.VarChar, 50).Value = UsernameTextBox.Text
cmd.Parameters.Add("#password", SqlDbType.Char, 32).Value = MD5Hash(PasswordTextBox.Text)
cmd.Parameters.Add("#email", SqlDbType.VarChar, 50).Value = EmailTextBox.Text
cmd.ExecuteNonQuery()
Catch ex As Exception
MessageBox.Show("Error while inserting record on table..." & ex.Message, "Insert Records")
Finally
con.Close()
End Try
All you have to do is use cmd.Parameters.Add with a parameter name and the right database type (the ones I guessed probably don't match up, so you'll want to change them), then set the value to the value you want used in the query. Parameter names start with an #.
It doesn't depend on the textbox. Don't compose a sql sentence joining strings like this:
"SELECT * FROM User WHERE UserName=" + tbName.Text + ...
Use stored procedures or parameterized queries and you'll be safe from SQL injection.
When you use parameters, the textbox content is used as a value, so it doesn't matter what it contains.
Use a parametrized query like this:
Using conn = New SqlConnection("some connection string")
Using cmd = New SqlCommand("SELECT Password FROM tblUser WHERE UserName = #Name", conn)
cmd.Parameters.Add(New SqlParameter("Name", UsernameTextBox.Text))
conn.Open()
Dim password As String = DirectCast(cmd.ExecuteScalar(), String)
Console.WriteLine(password)
End Using
End Using
This is injection safe!
I use the following connection string and am able to log into SQL 2008 R2 Server.
My.Settings.Item("CustomerConnectionString") = "Data Source=FAROOK-PC\SQLEXPRESS;Initial
Catalog= '" & Me.ComboBox1.Text & "'; uid = '" & Me.Login1.Text & "'; pwd = '" &
Me.Password1.Text & "'"
How do I display a messagebox on login failure.
Thank you.
use Try Catch Block. If connection fails use yor message box in catch block.
Dim sqlCnn As New SqlConnection
Dim connString as string = "Your Connection String"
Try
sqlCnn = New SqlConnection(connString)
sqlCnn.open()
Catch ex As SqlException
MsgBox("Login Failed")
End Try