vb2008 insert and update record using one button - sql

I am trying to make a glossary. I have a form with a listbox, 2 textboxes, and a save button.
The listbox is now populated with words from the database, and when a word is selected, its definition will display in textbox2.
The user can add a record by filling the textbox1 with a new word and textbox2 with its definition,and clicking the save button. If the new word already existed it will not allow to save a new record, also if there's a null value between the 2 textboxes. If it doesn't exist it will be inserted on the table and the new word will be added to the listbox.
The user can also update the record by selecting first a word on the list then edit the word and/or definition and clicking the save button.
I already got the updating part to work but I have problem in inserting a new record. I can't do it properly. The glossary table has only 2 fields: word, definition. Here's my code:
Dim myCmd As New MySqlCommand
Dim myReader As MySqlDataReader
Dim myAdptr As New MySqlDataAdapter
Dim myDataTable As New DataTable
Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click
Call Connect()
With Me
If Blank() = False Then
If Duplicate() = False Then
STRSQL = "insert into glossary values (#word, #def)"
myCmd.Connection = myConn
myCmd.CommandText = STRSQL
myCmd.Parameters.AddWithValue("word", txtNew.Text)
myCmd.Parameters.AddWithValue("def", txtdefine.Text)
myCmd.ExecuteNonQuery()
myCmd.Dispose()
MsgBox("Record Added")
Dim word As String
word = txtNew.Text
lstword.Items.Add(word)
'myConn.Close()
'Me.FillListbox()
Else
myConn.Open()
STRSQL = "Update glossary set word = #term, definition = #mean where word = #term"
myCmd.Connection = myConn
myCmd.CommandText = STRSQL
myCmd.Parameters.AddWithValue("term", txtNew.Text)
myCmd.Parameters.AddWithValue("mean", txtdefine.Text)
myCmd.ExecuteNonQuery()
myCmd.Dispose()
MsgBox("Record Updated", MsgBoxStyle.Information, "New word added")
End If
End If
End With
End Sub
Public Function Blank() As Boolean
Call Connect()
With Me
If .txtNew.Text = "" Or .txtdefine.Text = "" Then
Blank = True
MsgBox("Cannot save! Term and definition should not contain null value", MsgBoxStyle.Critical, "Unable to save")
Else
Blank = False
End If
End With
End Function
Public Function Duplicate() As Boolean
Call Connect()
With Me
STRSQL = "Select * from glossary where word = '" & txtNew.Text & "'"
myCmd.Connection = myConn
myCmd.CommandText = STRSQL
If myDataTable.Rows.Count <> 0 Then
Duplicate = True
'MsgBox("Word already exist. Please check the word.", MsgBoxStyle.Critical, "Duplicate.")
Else
Duplicate = False
End If
myConn.Close()
End With
End Function
this is my connection module:
Public myConnectionString As String
Public STRSQL As String
Public myConn As New MySqlConnection
Public Sub Connect()
With myConn
Try
If .State = ConnectionState.Open Then
.Close()
End If
myConnectionString = "Database=firstaidcqs;Server=localhost;Uid=root;Password="
.ConnectionString = myConnectionString
.Open()
'MsgBox("Successful Connection")
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical, "Connection Error")
.Close()
End Try
End With
End Sub
Public Sub Disconnect()
With myConn
.Close()
.Dispose()
End With
End Sub
How can I make this work properly?

You are using global variables in all the code above.
myConn and myCmd
in particular, you call Dispose on myCmd but I can't see anywhere the reinitialization of the object with New. Also, forgetting for a moment the myCmd.Dispose problem, you don't reset the myCmd parameters collection. In this way you end up with a wrong Parameter collection for the command executed, Also don't forget to open the connection for the insert part. (and close it for both parts)
You could easily avoid the use of unnecessary global variables
....
If Duplicate() = False Then
STRSQL = "insert into glossary values (#word, #def)"
Using myCmd = new MySqlCommand(STRSQL, myConn)
myConn.Open()
myCmd.Parameters.AddWithValue("word", txtNew.Text)
myCmd.Parameters.AddWithValue("def", txtdefine.Text)
myCmd.ExecuteNonQuery()
End Using
myConn.Close()
.....
Else
STRSQL = "Update glossary set word = #term, definition = #mean where word = #term"
Using myCmd = new MySqlCommand(STRSQL, myConn)
myConn.Open()
myCmd.Parameters.AddWithValue("term", txtNew.Text)
myCmd.Parameters.AddWithValue("mean", txtdefine.Text)
myCmd.ExecuteNonQuery()
End Using
myConn.Close()
.....
A better solution will be changing the Connect() method to return the initialized connection instead of using a global variable. In that way you could enclose also the creation and destruction of the connection in a Using statement
Using myConn as MySqlConnection = Connect()
.......
End Using
For this to work you need to change the code of Connect in this way
Public Function Connect() as MySqlConnection
Dim myConn As MySqlConnection
myConnectionString = "Database=firstaidcqs;Server=localhost;Uid=root;Password="
myConn = New MySqlConnection(myConnectionString)
myConn.Open()
return myConn
End Sub
No need of a Disconnect function because you will always use the Using statement that will close the connection for you, no need to have a global variable to keep the connection because you will reopen the connection every time you need it and close afterward. Don't think that this is not performant because ADO.NET implements connection pooling (It is an MSDN article for SqlServer, but the concept applies also to MySql)

yay!! I got it working now :D (my apology, it took me a long time to finish this..i'm still learning). Here's my final code:
Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click
Call Connect()
If Blank() = False Then
If Duplicate() = False Then
STRSQL = "insert into glossary values (#word, #def)"
Using myCmd = New MySqlCommand(STRSQL, myConn)
myConn.Open()
myCmd.Parameters.AddWithValue("word", txtNew.Text)
myCmd.Parameters.AddWithValue("def", txtdefine.Text)
myCmd.ExecuteNonQuery()
End Using
myConn.Close()
MsgBox("Record Added")
Dim word As String
word = txtNew.Text
lstword.Items.Add(word)
myConn.Close()
Else
STRSQL = "Update glossary set word = #term, definition = #mean where word = #term"
Using myCmd = New MySqlCommand(STRSQL, myConn)
myConn.Open()
myCmd.Parameters.AddWithValue("term", txtNew.Text)
myCmd.Parameters.AddWithValue("mean", txtdefine.Text)
myCmd.ExecuteNonQuery()
End Using
myConn.Close()
MsgBox("Record Updated", MsgBoxStyle.Information, "New word added")
Dim str As String
str = txtNew.Text
myConn.Close()
End If
End If
End Sub
Public Function Blank() As Boolean
Call Connect()
With Me
If .txtNew.Text = "" Or .txtdefine.Text = "" Then
Blank = True
MsgBox("Cannot save! Term and definition should not contain null value", MsgBoxStyle.Critical, "Unable to save")
Else
Blank = False
End If
End With
End Function
Public Function Duplicate() As Boolean
Dim dset As New DataSet
Call Connect()
With Me
STRSQL = "Select * from glossary where word = '" & txtNew.Text & "'"
myCmd.Connection = myConn
myCmd.CommandText = STRSQL
myAdptr.SelectCommand = myCmd
myAdptr.Fill(dset, "glossary")
myDataTable = dset.Tables("glossary")
If myDataTable.Rows.Count > 0 Then
Duplicate = True
'MsgBox("Word already exist. Please check the word.", MsgBoxStyle.Critical, "Duplicate.")
Else
Duplicate = False
End If
myConn.Close()
End With
End Function
I still used the my first module but I already removed the Disconnect() function. #Steve - thank you very much for the help sir, I'll try using what you suggested to me some time..maybe on my next program. God speed!! :)

Related

system login using query select 1

I am trying to code the login page, here is my code:
'login form code
Private Sub btnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click
Dim username As String = txtUsername.Text.Trim
Dim pwd As String = txtPassword.Text.Trim
Dim insertQry As String = "select 1 from UserInfo where username = '" & username & "' and userpassword = '" & pwd & "'"
Dim res As Boolean = executeReader(insertQry)
End Sub
database module
Imports System.Data.SqlClient
Module DBconn
Public conn_ As New SqlConnection("")
Public Function executeReader(ByVal query As String)
Try
Dim cmd As New SqlCommand(query, conn_)
conn_.Open()
Dim r2 As SqlDataReader = cmd.ExecuteReader()
Return True
Catch ex As Exception
Return False
End Try
End Function
End Module
My question is how to do validation of username and password check with select 1 query?
Take a look at this example, it does the following:
It returns the count of the primary key value in the SQL query (documentation)
It uses parameters to pass the values to the WHERE clause (documentation)
It uses ExecuteScalar to return a single value from the command (documentation)
Private Function ValidateLogin(ByVal username As String, ByVal password As String) As Boolean
Dim count As Integer = 0
'Declare the connection object
Using con As SqlConnection = New SqlConnection
'Wrap code in Try/Catch
Try
'Set the connection string
con.ConnectionString = "" 'TODO: set this value
'Create a new instance of the command object
Using cmd As SqlCommand = New SqlCommand("SELECT Count(UserInfoId) FROM UserInfo WHERE username=#username AND userpassword=#password", con)
'Parameterize the query
With cmd.Parameters
.Add("#username", SqlDbType.VarChar).Value = username
.Add("#password", SqlDbType.VarChar).Value = password
End With
'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
End If
End Try
End Using
'Return row count is greater than 0
Return count > 0
End Function

Syntax error (missing operator) in query expression 'Kad Matrik='DDWC2017/060550

Syntax error (missing operator) in query expression 'Kad Matrik='DDWC2017/060550 its that only problem then i dont how solve this coding
Dim strName = MatrikTextBox.Text
With objCon
.Close()
If .State = ConnectionState.Closed Then
.ConnectionString = strConnection
.Open()
Else
MessageBox.Show("Please Insert the correct Kad Matrik", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
End If
End With
ds.Clear()
strSQL = "Select * from DaftarMasukPelajar where Kad Matrik='" & MatrikTextBox.Text
da = New OleDbDataAdapter(strSQL, objCon)
da.Fill(ds, "DaftarMasukPelajar")
If ds.Tables("DaftarMasukPelajar").Rows.Count <> 0 Then
MaximizeBox = True
MinimizeBox = True
MsgBox("Hello! " + strName + vbNewLine +
"Log in successful", MsgBoxStyle.OkOnly,
"Welcome " + strName)
Form4.ShowDialog()
If Form4.Visible Then
Me.Hide()
End If
With objCon
.Close()
If .State = ConnectionState.Closed Then
.ConnectionString = strConnection
.Open()
Else
MessageBox.Show("Please Insert the correct Kad Matrik", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
End If
End With
This first bit of code doesn't make sense. You close the connection then check if it is closed and open it. Of course it is closed so the Else will never run. In any event, what would the corred Kad Matrik have to do with the connection being closed?
Form4.ShowDialog()
If Form4.Visible Then
Me.Hide()
End If
Why would you check if Form4 is visible when the line before shows it?
To validate a user you don't need a dataset and a dataadapter, just a command and a connection.
It is a good idea to keep your database code separate from the user interface code. The Using...End Using blocks ensure that your database objects are closed and disposed even if there is an error. Keep these objects local to the procedure and don't open the connection until the last possible minute, right before the .Execute...
Don't retrieve more data than you need. Don't Select * when all you need is to know if the record exists.
Private strConnection As String = "Your connection string"
Private Function ValidateUser(Matrik As String) As Boolean
Dim ReturnValue As Integer
Using cn As New OleDbConnection(strConnection)
Using cmd As New OleDbCommand("SELECT COUNT(*) FROM DaftarMasukPelajar WHERE [Kad Matrik] = #KadMatrik;", cn)
cmd.Parameters.Add("#KadMatrik", OleDbType.VarChar).Value = Matrik
cn.Open()
ReturnValue = CInt(cmd.ExecuteScalar)
End Using
End Using
If ReturnValue = 1 Then
Return True
Else
Return False
End If
End Function
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
If ValidateUser(MatrikTextBox.Text) Then
MaximizeBox = True
MinimizeBox = True
MsgBox("Hello! " & MatrikTextBox.Text & vbNewLine &
"Log in successful", MsgBoxStyle.OkOnly,
"Welcome " & MatrikTextBox.Text)
Form4.ShowDialog()
Me.Hide()
Else
MessageBox.Show("Sorry, invalid login")
End If
End Sub

SQL Server : delete user

I'm trying to write a query to delete a user registration from my SQL Server database, but when I try to delete a user, I get this error:
System.InvalidOperationException: 'ExecuteReader: Connection property has not been initialized.'
My code:
Public Class DeleteForm
Private Sub btnDelete_Click(sender As Object, e As EventArgs) Handles btnDelete.Click
Dim conn = New SqlConnection("Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=dbProject;Integrated Security=True")
Using cmd = New SqlCommand("SELECT * FROM tblLogin WHERE username = " & txtUsername.Text, conn)
conn.Open()
Dim reader As SqlClient.SqlDataReader = cmd.ExecuteReader
If reader.Read = True Then
If txtUserPass.Text = txtCheckPass.Text Then
Dim deleteOk As Integer = MessageBox.Show("This cant be undone!" & vbCrLf & "Are you sure?", "Warning!", MessageBoxButtons.YesNo, MessageBoxIcon.Warning)
If deleteOk = DialogResult.Yes Then
Dim queryDelete As String = "DELETE FROM tblLogin WHERE username = " & txtUsername.Text & " and password = " & txtPassword.Text
Dim cmdDelete As New SqlClient.SqlCommand(queryDelete, conn)
If conn.State = ConnectionState.Closed Then conn.Open()
reader.Close()
cmdDelete.ExecuteNonQuery()
MsgBox("Cancellazione eseguita correttamente!")
cmdDelete.Dispose()
conn.Close()
ElseIf deleteOk = DialogResult.No Then
End If
Else
MsgBox("The passwords arent matching!")
End If
Else
MsgBox("User not found")
conn.Close()
txtUsername.Clear()
txtUsername.Focus()
txtUserPass.Clear()
txtCheckPass.Clear()
End If
End Using
End Sub
End Class
You need to open connection before you can create a command.
i.e.
Dim conn = New SqlConnection("Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=dbProject;Integrated Security=True")
conn.Open()
Using cmd = New SqlCommand(....
However your current code contains SQL Injection. You should not concatenate strings go get your SQL. You should use parameters. See this answer for better explanation about the application.
Also it is never a good practice to store passwords in plain text. Ever. You should store hash of password only and compare the hashes rather than plain-text. Read this answer for reference. And more background info on why you should hash

DataGridView not showing all columns from table

I am currently creating a DataGridView within visual studio. The whole process is working fine and I have no errors. Apart from only one column is shown when executed when hitting 'Start' and is shown within a form.
For example in my process, only the "total cost" column is shown in the "bookingID" row in my DataGridView. I want all three columns to show, as in the code below states. The three rows are "bookingID", "paymentConfirmation" and "totalCost".
Here is the code:
Imports System.Data.Sql
Imports System.Data.SqlClient
Public Class Form4
Dim SQL As New SQLControl
Dim sqlCon As New SqlConnection
Private Sub Form4_Load(sender As Object, e As EventArgs) Handles MyBase.Load
With DGVData
.Rows.Clear()
.ColumnCount = 3
.Columns(0).HeaderText = "Booking ID"
.Columns(0).Width = 75
.Columns(0).DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
.Columns(0).HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter
.Columns(1).HeaderText = "Payment Confirmation"
.Columns(1).Width = 100
.Columns(1).HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter
.Columns(2).HeaderText = "Total Cost"
.Columns(2).Width = 100
.Columns(2).HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter
End With
LoadBookingData()
End Sub
Public Sub LoadBookingData()
Dim loadSQL As String = "SELECT * FROM booking"
Dim RowsCount As Integer
If SQL.SQLCon.State = ConnectionState.Closed Then
SQL.RunQuery(loadSQL)
RowsCount = SQL.SQLDS.Tables(0).Rows.Count
MsgBox(RowsCount)
' there are records !
DGVData.Rows.Add(RowsCount)
For i As Integer = 0 To RowsCount - 1
With DGVData
.Rows(i).Cells(0).Value = SQL.SQLDS.Tables(0).Rows(i).Item("bookingID")
.Rows(i).Cells(0).Value = SQL.SQLDS.Tables(0).Rows(i).Item("paymentConfirmation")
.Rows(i).Cells(0).Value = SQL.SQLDS.Tables(0).Rows(i).Item("totalCost")
End With
Next
Else
MsgBox("There is no records", MsgBoxStyle.Critical, "Sorry")
SQL.SQLDS.Reset()
SQL.SQLCon.Close()
End If
SQL.SQLDA.Fill(SQL.SQLDS, "GettingInfo")
RowsCount = SQL.SQLDS.Tables("GettingInfo").Rows.Count
If RowsCount < 1 Then
MsgBox("There is no records", MsgBoxStyle.Critical, "Sorry")
SQL.SQLDS.Reset()
SQL.SQLCon.Close()
Else
' there are records !
DGVData.Rows.Add(RowsCount)
For i As Integer = 0 To RowsCount - 1
With DGVData
.Rows(i).Cells(0).Value = SQL.SQLDS.Tables("GettingInfo").Rows(i).Item("bookingID")
.Rows(i).Cells(0).Value = SQL.SQLDS.Tables("GettingInfo").Rows(i).Item("paymentConfirmation")
.Rows(i).Cells(0).Value = SQL.SQLDS.Tables("GettingInfo").Rows(i).Item("totalCost")
End With
Next
End If
SQL.SQLDS.Reset()
SQL.SQLCon.Close()
End Sub
Here is the query within SQLControl:
Imports System.Data.SqlClient
Public Class SQLControl
Public SQLCon As New SqlConnection With {.ConnectionString = "Data Source=JENNIFER\DDAP2015;Initial Catalog=zachtravelagency;Integrated Security=True;"}
Public SQLcmd As SqlCommand
Public SQLDA As SqlDataAdapter
Public SQLDS As DataSet
Public Function HasConnection() As Boolean
Try
SQLCon.Open()
SQLCon.Close()
Return True
Catch ex As Exception
MsgBox(ex.Message)
End Try
Return False
End Function
Public Sub RunQuery(Query As String)
Try
SQLCon.Open()
' CREATE COMMAND
SQLcmd = New SqlCommand(Query, SQLCon)
' FILL DATASET
SQLDA = New SqlDataAdapter(SQLcmd)
SQLDS = New DataSet
SQLDA.Fill(SQLDS)
SQLCon.Close()
Catch ex As Exception
MsgBox(ex.Message)
' MAKE SURE CONNECTION IS CLOSED
If SQLCon.State = ConnectionState.Open Then
SQLCon.Close()
End If
End Try
End Sub
An example in code on how to fix this would be much appreciated. Thanks.
It is hard to sort through all the capabilities of .Net to figure out which ones to use. You are writing a lot of code that could be moved to a library.
Here are two Functions() that have saved me a lot of time:
Function GetDataTable(ByVal SQL As String, Optional ByVal ConnectString As String = "", Optional ByVal SingleRow As Boolean = False) As DataTable ' returns read only Datatable
Try
If ConnectString.Length = 0 Then ConnectString = g.OISConnectString
Using con As New System.Data.SqlClient.SqlConnection(ConnectString)
Dim rdr As Data.SqlClient.SqlDataReader
con.Open()
Dim cmd As New SqlCommand(SQL, con)
If SingleRow Then
rdr = cmd.ExecuteReader(CommandBehavior.SingleRow Or CommandBehavior.CloseConnection)
Else
rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection)
End If
Dim dt As New DataTable
dt.Load(rdr)
rdr.Close()
Return dt
End Using
Catch ex As Exception
ExpLog.LogMsgBox(ex, ex.Message, , "GetDataTable", "SQL: " & SQL)
Return Nothing
End Try
End Function
Function GetDataView(ByVal SQL As String, Optional ByVal ConnectString As String = "") As DataView ' returns read only Dataview
Try
Dim dt As DataTable
dt = GetDataTable(SQL, ConnectString)
If dt.Rows.Count = 0 Then
Return Nothing
Else
Dim dv As New DataView(dt)
Return dv
End If
Catch ex2 As NullReferenceException
Return Nothing
Catch ex As Exception
ExpLog.LogMsgBox(ex, ex.Message, , "GetDataView", "SQL: " & SQL)
Return Nothing
End Try
End Function
GetDataTable returns a read-only table that loads more quickly than a full featured table. The table can be used as the RecordSource for a DataGridView.
Sometimes I use GetDateView when I what to use the filter capability with the DataGridView. Just use the returned DataView as the record source and then you can set the DataView filter to control what is shown in the grid.

How can I make my MsgBox Appear if the Equip_No is not equal to the value in the Equip_no Textbox?

I am using a visual studio 2010 and Microsoft Sql server 2005.
I want to make the MsgBox("Unable to delete. Equipment Number is not found!", vbInformation, "Error") appear whenever a user enters an incorrect Equip_No.
Any help is appreciated. Thanks!
Private Sub Delete_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Delete.Click
If MessageBox.Show("Do you really want to delete this record?", "Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) = DialogResult.No Then
MsgBox("Operation cancelled")
Exit Sub
End If
'If Command.CommandText = "SELECT FROM dbo.inhouse_hardware_marterfile_tbl WHERE Equip_No = #Equip_No" Then
Try
Dim Command As New SqlCommand
Dim con As New SqlConnection("Server=HPC-107;Database=MRPdb;integrated security= ...")
con.Open()
Command.Connection = con
Command.CommandText = " DELETE FROM dbo.inhouse_hardware_marterfile_tbl WHERE Equip_No = '" & Equip_No.Text & "'"
Dim da As New SqlDataAdapter
da.SelectCommand = Command
da.DeleteCommand = Command
Command.ExecuteNonQuery()
msgdeleted()
con.Close()
Catch ex As Exception
End Try
'Else : MsgBox("Unable to delete. Equipment Number is not found!", vbInformation, "Error")
'End If
'Command.Parameters.AddWithValue("#Equip_No", Equip_No.Text)
Grid()
ClearTextBoxes()
End Sub
The ExecuteNonQuery method returns an integer that is the number of rows affected by the command.
In your case, if the number is zero, then you could print your message
Dim result = Command.ExecuteNonQuery()
if result = 0 then
MessageBox.Show("Unable to delete. Equipment Number is not found!")
else
MessageBox.Show("Record deleted")
End if
Said that, please take note that.
An SqlDataAdapter is not required in this context.
You should use a parameterized query and not a string concatenation
Dim Command As New SqlCommand
Dim con As New SqlConnection("Server=HPC-107;Database=MRPdb;integrated security= ...")
con.Open()
Command.Connection = con
Command.CommandText = "DELETE FROM dbo.inhouse_hardware_marterfile_tbl " & _
"WHERE Equip_No = #eqno"
Command.Parameters.AddWithValue("#eqno", Equip_No.Text)
Dim result = Command.ExecuteNonQuery()