SQL to search for encrypted values not working - sql

I am using a button to trigger a SELECT statement, and based off of the criteria the user enters in 2 text boxes (SearchFirstTxt, SearchLastTxt), I send the Text values of those text boxes through an encryption class to find their match
I return them in a SqlDataAdapter and use it to fill a DataTable. I then use DataGridView.DataSoruce = dt to add it to the DGV.
My question: If the user leaves both text boxes blank and clicks the "SearchBtn", it doesn't select all of the records. It actually only selects records with the same encrypted values.
Here is the code:
eFirst = clsEncrypt.EncryptData(SearchFirstTxt.Text.Trim.ToUpper)
eLast = clsEncrypt.EncryptData(SearchLastTxt.Text.Trim.ToUpper)
conn.Open()
cmd.Connection = conn
If SearchFirstTxt.Text = "" Then
cmd.CommandText = "Select * FROM Participant Where LAST_NM_TXT = '" & eLast & "' ; "
ElseIf SearchLastTxt.Text = "" Then
cmd.CommandText = "Select * FROM Participant WHERE FIRST_NM_TXT = '" & eFirst & "' ; "
Else
cmd.CommandText = "SELECT * FROM PARTICIPANT;"
End If
Dim adapter As New SqlDataAdapter(cmd)
adapter.Fill(dt)
DataGridView1.DataSource = dt
Try
For i As Integer = 0 To dt.Rows.Count - 1
dt.Rows(i)("FIRST_NM_TXT") = clsEncrypt.DecryptData(eFirst)
dt.Rows(i)("LAST_NM_TXT") = clsEncrypt.DecryptData(eLast)
Next
Catch ex As Exception
MessageBox.Show("Error")
Finally
conn.Close()
End Try
How can I select ALL of the records from the Participant dbo?
The result set looks like this if the text boxes are left blank:
Edit: I switched my code, and it retrieves ALL of the results, however, now I am having difficulty returning them. (They return as encrypted, but not decrypted)
Here are the changes:
If SearchFirstTxt.Text = "" And SearchLastTxt.Text = "" Then
cmd.CommandText = "SELECT * FROM PARTICIPANT;"
ElseIf SearchLastTxt.Text = "" Then
cmd.CommandText = "Select * FROM Participant WHERE FIRST_NM_TXT = '" & eFirst & "' ; "
ElseIf SearchFirstTxt.Text = "" Then
cmd.CommandText = "Select * FROM Participant Where LAST_NM_TXT = '" & eLast & "' ; "
End If

If I understand your requirements correctly, you need to add a check for the other search text when you try to search your encrypted data
If SearchFirstTxt.Text = "" AndAlso SearchLastTxt.Text <> "" Then
' Search the last only if you have a last and not a first'
cmd.CommandText = "Select * FROM Participant Where LAST_NM_TXT = #searchLast"
cmd.Parameters.AddWithValue("#searchLast", eLast)
ElseIf SearchLastTxt.Text = "" AndAlso SearchFirstTxt.Text <> "" Then
' Search the first only if you have a first and not a last'
cmd.CommandText = "Select * FROM Participant WHERE FIRST_NM_TXT = #searchFirst"
cmd.Parameters.AddWithValue("#searchFirst", eFirst)
ElseIf SearchFirstTxt.Text = "" AndAlso SearchLastText.Text = "" Then
' Both emtpy so search everything'
cmd.CommandText = "SELECT * FROM PARTICIPANT;"
Else
' Both filled so search exactly (not sure if this is needed)'
cmd.CommandText = "Select * FROM Participant " & _
"WHERE FIRST_NM_TXT = #searchFirst " & _
"OR LAST_NM_TXT = #searchLast"
cmd.Parameters.AddWithValue("#searchFirst", eFirst)
cmd.Parameters.AddWithValue("#searchLast", eLast)
End If
Dim adapter As New SqlDataAdapter(cmd)
adapter.Fill(dt)
Notice that I have removed your string concatenation and used a parameterized query. It is safer (avoids Sql Injection) and remove parsing problems (what if your encrypted text contains a single quote?)
Supposing then that you want to show the decrypted data you apply your deCryptData function to the values in the datatable, not to the same values used for the search (you already know the clear text)
Try
For i As Integer = 0 To dt.Rows.Count - 1
dt.Rows(i)("FIRST_NM_TXT") = clsEncrypt.DecryptData(dt.Rows(i)("FIRST_NM_TXT").ToString)
dt.Rows(i)("LAST_NM_TXT") = clsEncrypt.DecryptData(dt.Rows(i)("LAST_NM_TXT").ToString)
Next
Catch ex As Exception
MessageBox.Show("Error")
Finally
conn.Close()
End Try

Related

VB.net and SQL .... For multiple read of database table

Im am currently coding an handsfree RFID attendance monitoring system where i could just swipe and record details automatically...
I've been in trouble about this piece of code where i need to fetch a table and another table inorder to check if there is an existing record in table1 as the details and table2 as a record in in/out. I wanted it as much as possible to be able to be in a 1 while loop
**
I kept getting this error **
Invalid attempt to access a field before calling Read()
`
Private Sub TextBox7_KeyDown(sender As Object, e As KeyEventArgs) Handles TextBox7.KeyDown
If e.KeyCode = Keys.Enter Then
'Dim idnum = Val(TextBox7.Text
Dim statu As String = ""
Dim idnum = (TextBox7.Text)
Dim record As String = ""
TextBox2.Text = ""
TextBox3.Text = ""
TextBox4.Text = ""
ConnectToDB()
sql = "select * from rfidmaintest.student_details_dub where f9 = '" & idnum & "'"
cmd = New MySqlCommand(sql, cn)
dr = cmd.ExecuteReader
While dr.Read
TextBox2.Text = (dr("f2"))
TextBox3.Text = (dr("f9"))
TextBox4.Text = (dr("f4"))
TextBox5.Text = (dr("f14"))
TextBox6.Text = (dr("f3"))
TextBox7.Clear()
dr.Close()
cn.Close()
'ANOTHER FETCH
ConnectToDB()
sql = "select * from rfidmaintest.monitoring where id_num = '" & idnum & "'"
cmd = New MySqlCommand(sql, cn)
dr = cmd.ExecuteReader
**Invalid attempt to access a field before calling Read()**
If (dr("entry_record")) = String.Empty Then
status.Text = "IN"
End If
If status.Text = "IN" Then
status.Text = (dr("entry_record"))
record = "OUT"
ElseIf status.Text = "OUT" Then
record = "IN"
ElseIf status.Text = String.Empty Then
record = "IN"
End If
End While
dr.Close()
cn.Close()
`
I tried to call the table
You need another dr.read for the second query or you can use another reader, for example like dr2.read.
Your first While dr.read already closed with dr.close, you need to reopen the reader to continue to read the second query

Showing the messagebox only once in a loop vb.net

I have this loop that pops out a message box every time the condition is true.
For i = 0 To DataGridView1.Rows.Count - 1
Dim c As Boolean
c = DataGridView1.Rows(i).Cells(0).Value
If c = True Then
cmd3.Connection = con
con.Open()
cmd3.CommandText = "insert into student select * from stud where studentno = '" & DataGridView1.Rows(i).Cells(1).Value.ToString & "' delete from stud where studentno = '" & DataGridView1.Rows(i).Cells(1).Value.ToString & "'"
dr3 = cmd3.ExecuteReader()
MessageBox.Show("Account approved.")
con.Close()
Else
End If
Next
The messagebox shows as many times as the checked row. And I want to show it just once. I relocate my messagebox everywhere but it does not work. I searched but did not come up for an answer.
I tried moving it outside the loop but the problem is, the message box still shows even the condition is false.
Thanks!
One approach would be to create a counter for successful approvals and another counter for unsuccessful approvals and display these after completing the loop. The counters are incremented in the loop depending on the result of the boolean c in each iteration.
Dim iSuccessCount As Integer
Dim iFailedCount As Integer
For i = 0 To DataGridView1.Rows.Count - 1
Dim c As Boolean
c = DataGridView1.Rows(i).Cells(0).Value
If c = True Then
iSuccessCount +=1
cmd3.Connection = con
con.Open()
cmd3.CommandText = "insert into student select * from stud where studentno = '" & DataGridView1.Rows(i).Cells(1).Value.ToString & "' delete from stud where studentno = '" & DataGridView1.Rows(i).Cells(1).Value.ToString & "'"
dr3 = cmd3.ExecuteReader()
con.Close()
Else
iFailedCount += 1
End If
Next
Dim sb As New StringBuilder
sb.Append(iSuccessCount.ToString)
sb.Append(If(iSuccessCount = 1, " account was ", " accounts were "))
sb.Append("approved.")
sb.Append(Environment.NewLine)
sb.Append(iFailedCount.ToString)
sb.Append(If(iFailedCount = 1, " account was ", " accounts were "))
sb.Append("not approved.")
MessageBox.Show(sb.ToString)

Search through the database using a combobox, if an item is in a database, prompt will appear

Good day everyone.
I'm making a POS and Inventory Management System and I'm having a problem with this particular module as of now.
When adding an item to purchase order list, if an item is already in the purchaseorder database, the system will prompt that there is already a pending order. I've done the prompt, but the adding to the database was kinda messed up. It doesn't do a thing at all. The code there is working when I remove the ds.hasrows and while dr.read conditions. This is my code:
Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click
Ceiling = CInt(txtCeiling.Text)
TotalQuantity = CurrentItemQuantity + CInt(txtPurchaseQty.Text)
If TotalQuantity > Ceiling Then
MsgBox("Exceeds Ceiling Point.")
Else
sqlString = "SELECT PRODUCT_ID FROM posinventory.purchaseorder WHERE purchaseorder.PRODUCT_ID = '" & cboProductID.Text & "'"
cmd = New MySqlCommand(sqlString, con)
dr = cmd.ExecuteReader
If dr.HasRows Then
While dr.Read
If CurrentItem = dr.Item("PRODUCT_ID") Then
MsgBox("Product has pending order.")
cboProductID.Focus()
Else
sqlString = "INSERT INTO posinventory.purchaseorder (PRODUCT_ID, PURCHASE_QUANTITY, DATE_PURCHASED, TIME_PURCHASED) VALUES (" & cboProductID.Text & ", '" & txtPurchaseQty.Text & "', '" & txtDate.Text & "', '" & txtTime.Text & "')"
Try
cmd = New MySqlCommand(sqlString, con)
dr = cmd.ExecuteReader
dr.Close()
Catch ex As Exception
MsgBox("Error saving to database. Error is: " & ex.Message)
Exit Sub
End Try
MsgBox("Transaction Complete.")
lvOrderList.Items.Clear()
sqlString = "SELECT posinventory.purchaseorder.TRANSACTION_ID, posinventory.products.PRODUCT_ID, posinventory.products.PRODUCT_NAME, posinventory.products.SUPPLIER_NAME, posinventory.purchaseorder.PURCHASE_QUANTITY, posinventory.purchaseorder.DATE_PURCHASED, posinventory.purchaseorder.TIME_PURCHASED FROM posinventory.purchaseorder, posinventory.products WHERE posinventory.purchaseorder.PRODUCT_ID = posinventory.products.PRODUCT_ID"
cmd = New MySqlCommand(sqlString, con)
da = New MySqlDataAdapter(cmd)
ds = New DataSet
da.Fill(ds, "Table")
Dim i As Integer = 0
Dim j As Integer = 0
For i = 0 To ds.Tables(0).Rows.Count - 1
For j = 0 To ds.Tables(0).Columns.Count - 1
itemcol(j) = ds.Tables(0).Rows(i)(j).ToString()
Next
Dim lvi As New ListViewItem(itemcol)
Me.lvOrderList.Items.Add(lvi)
Next
grpCreateOrder.Enabled = False
grpOrderList.Enabled = True
cboProductID.SelectedIndex = -1
txtPurchaseQty.Text = ""
txtDate.Text = ""
txtTime.Text = ""
txtProductName.Text = ""
txtSupplier.Text = ""
txtQty.Text = ""
txtCeiling.Text = ""
btnBack.Enabled = True
End If
End While
End If
dr.Close()
End If
End Sub
I think its because you are inside of a loop using a cmd and dr. While you are in there you are then defining a new cmd and dr.
Try using different names eg cmd2, dr2.

EXTRACT query in Vb.net using sql

This is my code then the problem is it will not show the information in the gridlist. I want to make inner join of my two tables but it doesn't work with my codes. What will be the alternative way of this? Thank you so much for answering.
Dim sqlQuery As String = "SELECT Persons.pr_id, Persons.pr_fname, Persons.pr_mname, Persons.pr_lname, Persons.pr_address, Users.UserName, Users.phone_num FROM Persons" & _
"INNER JOIN Users ON Persons.pr_id = Users.pr_id" & _
" WHERE pr_id='" & TextBox1.Text & "'"
Dim table As New DataTable
cn.Close()
cn.Open()
With cmd
.CommandText = sqlQuery
.Connection = cn
End With
With cmd
.CommandText = sqlQueryUser
.Connection = cn
End With
With sqla
.SelectCommand = cmd
.Fill(table)
End With
If ListView1.SelectedItems.Count > 0 Then
'Button20.Visible = True
'Button10.Visible = True
'RichTextBox2.Enabled = False
'senbyCombo.Enabled = False
'group_sendCombo.Enabled = False
'title.Enabled = False
'ListView3.Enabled = True
id = ListView1.SelectedItems(0).Text
TextBox1.Text = ListView1.SelectedItems(0).SubItems(0).Text
TextBox2.Text = ListView1.SelectedItems(0).SubItems(1).Text
TextBox3.Text = ListView1.SelectedItems(0).SubItems(2).Text
TextBox4.Text = ListView1.SelectedItems(0).SubItems(3).Text
TextBox5.Text = ListView1.SelectedItems(0).SubItems(4).Text
TextBox7.Text = ListView1.SelectedItems(0).SubItems(6).Text
End If
cn.Close()
your pr_id is ambiguous change your query like this :
Dim sqlQuery As String = "SELECT Persons.pr_id, Persons.pr_fname, Persons.pr_mname, Persons.pr_lname, Persons.pr_address, Users.UserName, Users.phone_num FROM Persons" & _
"INNER JOIN Users ON Persons.pr_id = Users.pr_id" & _
" WHERE Persons.pr_id='" & TextBox1.Text & "'"

Vb.net with access database: How can you help me simplify these codes?

this is my code:
'Set up connection string
Dim cnString As String
cnString = "Provider=Microsoft.Jet.OLEDB.4.0;Persist Security Info=False;Data Source=..\data\testingDB.mdb"
Dim sqlQRY As String = "SELECT * " & _
"FROM users " & _
"WHERE firstName = '" & TextBox1.Text & "' " & _
" AND lastName = '" & TextBox2.Text & "'"
'Create connection
Dim conn As OleDbConnection = New OleDbConnection(cnString)
Try
' Open connection
conn.Open()
'create data adapter
Dim da As OleDbDataAdapter = New OleDbDataAdapter(sqlQRY, conn)
'create dataset
Dim ds As DataSet = New DataSet
'fill dataset
da.Fill(ds, "user")
'get data table
Dim dt As DataTable = ds.Tables("user")
'display data
Dim row As DataRow
If TextBox1.Text = dt.Rows(0).Item(1) And TextBox2.Text = dt.Rows(0).Item(2) And dt.Rows(0).Item(5) = 10 Then
MsgBox("10")
ElseIf TextBox1.Text = dt.Rows(0).Item(1) And TextBox2.Text = dt.Rows(0).Item(2) And dt.Rows(0).Item(5) = 9 Then
MsgBox("9")
ElseIf TextBox1.Text = dt.Rows(0).Item(1) And TextBox2.Text = dt.Rows(0).Item(2) Then
MsgBox("SUCCESS")
Else
MsgBox("fail")
End If
Catch ex As OleDbException
MsgBox("Error: " & ex.ToString & vbCrLf)
Finally
' Close connection
conn.Close()
End Try
I'm trying it to make it simple with the same results. As you can see the if-else statements were messy but it works 100%. I do want the if-else statements to be simple and works the same as above.
Edited to check value of row(5) for DbNull values
try this for if-else statements:
Dim row As DataRow = dt.Rows(0)
Dim r5 as Object = row(5)
If IsDbNull(r5) then r5 = 0
If TextBox1.Text = row(1) And TextBox2.Text = row(2) Then
Select Case r5
Case 10, 9 : MsgBox(r5)
Case Else : MsgBox("SUCCESS")
End Select
Else
MsgBox("fail")
End If
Dim cmd as New OledbCommand
Dim sqlQRY As String = "SELECT count(*) " & _
"FROM users " & _
"WHERE firstName = #fname " & _
" AND lastName = #lname"
cmd.parameters.add("#fname",TextBox1.Text)
cmd.parameters.add("#lname",TextBox2.Text)
Dim Cnt as Integer
cmd = new oledbcommand(sqlQRy,con)
Cnt = Convert.ToInt32( cmd.ExecuteScalar())
if Cnt>=1 then
msgbox("Success")
else if
msgbox("Failure")
end if
You must be aware that your SQL could logically return more than 1 row. You need to make sure that when you read data that you intend to test in this way, that your SQL uses a primary key and return 1 row only otherwise, problems could happen when more data is added. I suggest you first ensure that exactly 1 row is returned before you perform your if test (see my comment to #SenthilKumar). You need to send appropriate message to user when no rows are found and not perform the test.
If you get exactly 1 row back, you have to ensure that the data is not null (if applicable, this depends on how your columns are defined).
Remember that data that comes form UI could be padded with blanks or be in mixed case. You may need to watch for this.
Your IF statement is not too complex as is.I am not sure what you are testing exactly, but one can observe that you are using the following conditions:
TextBox1.Text = dt.Rows(0).Item(1) And TextBox2.Text = dt.Rows(0).Item(2) And dt.Rows(0).Item(5)
TextBox1.Text = dt.Rows(0).Item(1) And TextBox2.Text = dt.Rows(0).Item(2) And dt.Rows(0).Item(5)
TextBox1.Text = dt.Rows(0).Item(1) And TextBox2.Text = dt.Rows(0).Item(2)
You can see that the the expression
dt.Rows(0).Item(1) And TextBox2.Text = dt.Rows(0).Item(2) is common. You can assign the value to a Boolean expression and use it in your test.
You also should not include non-database processing in the scope of your try.
Just more little simpler ..
If TextBox1.Text = dt.Rows(0).Item(1) And TextBox2.Text = dt.Rows(0).Item(2)
MsgBox("SUCCESS - " & format(dt.Rows(0).Item(5)))
Else
MsgBox("fail")
End If