How to edit a specific entity inside an access database - vb.net

I made an access database which stores all the flashcards that the user has created.
Here it is:
When the user creates a flashcard, the difficulty is set to 3 and the user is able to change the difficulty through txtDifficulty
Private Sub btnSubmit_Click(sender As Object, e As EventArgs) Handles btnSubmit.Click
Dim sql As String
sql = "UPDATE flashcards set difficulty = " & TxtDifficulty.Text 'Changes difficulty to user input
runSQL(sql) 'runs SQL
End Sub
The problem with the above code is that it edits every single flashcard inside the database rather than just the individual flashcard.
Private Sub btnSubmit_Click(sender As Object, e As EventArgs) Handles btnSubmit.Click
Dim sql As String
sql = "UPDATE flashcards set difficulty = " & TxtDifficulty.Text 'Changes difficulty to user input
sql = sql & "WHERE Front = " & txtFront.Text
runSQL(sql) 'runs SQL
End Sub
I edited the code to the above which I thought that it will only edit where Front in the database is equal to txtfront.text which is the textbox where the flashcard appears to the user but this just produces an error.
I was wondering how to only edit the specific flashcard that the user is on. Im guessing it might be something to do with the unique identifier in the access database but im not sure how to implement it

Your idea to "only edit where Front in the database is equal to txtfront.text" is a good one, but concatenating values into an SQL query is fraught with potential problems.
If you pass the values to the query as SQL parameters then you don't need to worry about putting quotes around values, which is one of the problems for the code in the question.
You can write the SQL query over more than one line to make it easier to read: extra whitespace in the query is OK, but no whitespace (another of the problems for the code in the question) is a problem, usually a syntax error.
If you keep the database operation in a separate method, it keeps each part of the code in its own method, which makes it easier to be sure that each part is doing what it should and also easier to maintain.
Sub UpdateDifficultyLevel(front As String, difficulty As Integer)
Dim sql = "UPDATE flashcards SET difficulty = ?
WHERE Front = ?"
Using conn As New OleDbConnection("yourConnectionStringHere"),
cmd As New OleDbCommand(sql, conn)
cmd.Parameters.Add("#difficulty", OleDbType.Integer).Value = difficulty
cmd.Parameters.Add("#front", OleDbType.VarWChar).Value = front
conn.Open()
cmd.ExecuteNonQuery()
End Using
End Sub
Private Sub btnSubmit_Click(sender As Object, e As EventArgs) Handles btnSubmit.Click
Dim difficulty As Integer
If Integer.TryParse(TxtDifficulty.Text, difficulty) Then
Dim front = txtFront.Text
UpdateDifficultyLevel(front, difficulty)
Else
' tell user that the difficulty must be a number
End If
End Sub
The parameters are represented by question marks in the query, and you have to add the parameters in the same order as they are used. Giving a name to each parameter ("#front", etc.) is just to make it easier to see which one is which (the name would actually be used if another database, such as SQL Server, was used).
The Using statement makes sure that any "unmanaged resources" are released after they've been used.
You might also need to use the UserID in the update query, but I could not gauge that from the question.

Related

How to edit a record in an access database - visual basic

I want to edit a specific record in an access database but I keep on getting errors
this is the database I want to edit:
Access database
these are flashcards that the user has created and stored in an access database. What I want is that the user is able to edit the difficulty so it appears more/less often
This is the module:
Module Module1
Public Function runSQL(ByVal query As String) As DataTable
Dim connection As New OleDb.OleDbConnection("provider=microsoft.ACE.OLEDB.12.0;Data Source=flashcard login.accdb") 'Establishes connection to database
Dim dt As New DataTable 'Stores database in table called dt
Dim dataadapter As OleDb.OleDbDataAdapter
connection.Open() 'Opens connection
dataadapter = New OleDb.OleDbDataAdapter(query, connection)
dt.Clear() 'Clears datatable
dataadapter.Fill(dt) 'Fills datatable
connection.Close()
Return dt
End Function
End Module
And here is the button that the user can press to edit the database:
Private Sub btnSubmit_Click(sender As Object, e As EventArgs) Handles btnSubmit.Click
Dim sql As String
sql = "UPDATE flashcards set difficulty = '" & TxtDifficulty.Text
runSQL(sql)
End Sub
The difficulty column in the database should be able to be edited by the user through the value they entered in txtDifficulty.text
Good to hear I found the problem with the apostrophe.
I am going to need a where statement but the problem I have is that the user can create as much flashcards as they want so how would I write the where statement?
An INSERT statement does not have a WHERE clause but an UPDATE does and is usually by a primary key.
Look at how I add a new record ignoring mHasException and specifically using parameters. In this case a List is used but with little effort an array of DataRow can be passed instead.
Here is an example for updating a record with a DataRow.
To get other code samples for ms-access see the following repository.
In closing, in the above repository I don't get into all possibilities yet there should be enough there to get you going. And when reviewing code I flip between Add for adding a parameter and AddWithValue while Add is the recommend way but both are shown to see differences. see also Add vs AddWithValue.

How to verify login permissions using a DataSet and QueryBuilder?

I wasnt quite sure how to properly write the question so bear with me please, here i'll explain as much as I can. And sorry if its too long.
I am building a basic school project that allows employees to register their time-in and time-out of the job to an Access Database, but I am currently struggling with the Login Form.
After many attempts I decided to go the easy way and use both the DataSet designer and the Query Builder from Visual Studio.
This is what I have right now:
An "EmpleadosDataSet" with a "_tblUser" DataTable and its TableAdapter, this adapter uses a query which I've named "GetDataLogin". Heres an image for reference EmpleadosDataSet Design View
What the query does is fill the "_tblUserDataTable" like this:
SELECT [ID EMPLEADO], USUARIO, CONTRASEÑA, PERMISOS
FROM [_tblUser]
WHERE (USUARIO = ?) AND (CONTRASEÑA = ?)
(Notice how I'm not using the PERMISOS at all after selecting it because that´s what I need help with)
For this to work on my code I instantiate my _tblUserDataTable from the EmpleadosDataSet and its TableAdapter:
Private dtLogin As New EmpleadosDataSet._tblUserDataTable
Private taLogin As New EmpleadosDataSetTableAdapters._tblUserTableAdapter
Then I pass both onto a button click event with this:
Private Sub _Button2_Acceder_Click(sender As Object, e As EventArgs) Handles _Button2_Acceder.Click
dtLogin = taLogin.GetDataLogin(_TxtUsuario.Text, _TxtContrasena.Text)
If dtLogin.Count > 0 Then
MsgBox("Bienvenido")
Else
MsgBox("No esta registrado")
End If
End Sub
This works just fine, however, I want to open a different form depending on whether the employee is an "user" or an "admin". This information is stored in the same dataset on a column named "PERMISOS", but I have no clue how to make the query that selects the value from said column and verify it.
My best bet is that I´ll have the query do SELECT PERMISOS and somehow assign that value to a variable that I can then verify with an If statement?
Something with this structure (this is just an example of what I need but I do not know if its the correct procedure, also, value from PERMISOS column is not a variable name or anything, im putting it for reference of what i need to be there):
If **value from PERMISOS column** = "admin" Then
Me.Hide()
Form2_admin.Show()
ElseIf **value from PERMISOS column** = "user" Then
Me.Hide()
Form3_user.Show()
I am not sure if that would be correct at all, bear with me, I havent been able to find how to even do that, assign the value of the column that I already selected with the query to a variable. Every info about this that I find is from people who rather code the whole database connection and queries themselves, haven´t found anything using the designer and query builder that refers to user permissions.
So that's basically what I need help with, how to either use a query or something else to verify user permissions like that, in other words, how to get the -value from PERMISOS column-
And just if clarification is needed, I did also use the Data Source wizard to connect to the Access Database, as it was the easier way, my DataSets are connected to that and filled with the info from it
PS: I understand some of my methods are incorrect, such as storing passwords as plain text, but please understand this is a simple practice about WindowsForms in general, not trying to learn security or others as of right now, will eventually do but right now I just need this.
If you can learn to write some basic ADO.net code, you will be able to get the data you want in the format your want.
First the user interface code. You pass the values in the 2 text boxes to a function and get back the data you want. Notice that the user interface doesn't know or care where the data is coming from. It is completely disconnected from the database.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click, Button2.Click
Dim permission = ValidateEmployee(_TxtUsuario.Text, _TxtContrasena.Text)
If permission = "admin" Then
Me.Hide()
Form2_admin.Show()
ElseIf permission = "user" Then
Me.Hide()
Form3_user.Show()
Else
MessageBox.Show("No esta registrado")
End If
End Sub
The data access code is all in the function and this function doesn't know anything about the user interface. It has not idea that the parameters are coming from text boxes. If you switched this to a web app, you could still use this function; just change where the parameters values are coming from.
The Using blocks ensure that your database objects are closed and disposed even if there is an error.
We can use named parameters with Access but Access pays no attention to the name. For Access (OleDb) these are positional parameters which means that the order that they appear in the sql query must match the order that they are added to the parameters collection (cmd.Parameters.Add)
Private ConStr As String = "Your connection string"
Private Function ValidateEmployee(user As String, pword As String) As String
Dim permissions As String
Using cn As New OleDbConnection(ConStr),
cmd As New OleDbCommand("Select PERMISOS
From _tblUser
Where USUARIO = #User
AND CONTRASEÑA = #Password;", cn)
cmd.Parameters.Add("#User", OleDbType.VarWChar).Value = user
cmd.Parameters.Add("#Password", OleDbType.VarWChar).Value = pword
cn.Open()
Using reader = cmd.ExecuteReader
If reader.HasRows Then
reader.Read()
permissions = reader("PERMISOS").ToString
Else
permissions = ""
End If
End Using
End Using
Return permissions
End Function
The only big problem left is storing passwords as plain text. They should be salted and encrypted to be safe but that is an issue for another day.

how to populate checkedlist box in vb using search item text box

i made program to populate employe name in checkedlist box. now i need a search box for searching items from the combo box.when i typing the matching items must list out in the checked list box.for that how i code in vb.net ?.
in key press even driven section i give the code but its not working properly.Please provide sufficient information. my code is given below
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
Dim conobj As Class1
conobj = New Class1
conobj.connection()
Dim str1 = "select distinct e.vc_empname xxxxxxx e.vc_empname like '" & Me.TextBox1.Text & "%' order by e.vc_empname"
conobj.readdata1(str1)
CheckedListBox1.DataSource = conobj.ds.Tables(0)
CheckedListBox1.DisplayMember = "vc_empname"
CheckedListBox1.ValueMember = "vc_empname"
End Sub
Even if "but its not working properly" is very vague i'll give it a try. Use the Asclause to specify the alias. Also, use Where to filter records:
Dim str1 = "select distinct e.vc_empname As xxxxxxx e.vc_empname Where vc_empname like '%" & Me.TextBox1.Text & "%' order by e.vc_empname"
Note that you should always use sql-parameters to prevent sql-injection and other issues. I also strongly discourage from global connection classes like your Class1 which also holds the connection. All the more if it is Shared/static. This can cause issues with connection-pooling which is enabled by default. It's also more difficult to use the Using-statement (which you should use) if you don't expose the connection and other ADO.NET objects. It's also difficult to pass the sql-parameters if the method readdata1 doesn't accepts them.

I am trying to alphabetize a combo box using a query in my vb code. How do i get it to work Im having problems?

I want to know if its possible to somehow use a query in my vb code to alphabetize a list in a combo box that I have a dataset connected to?
Here is my code:
Private Sub ValueSourceAvailabilityBindingNavigatorSaveItem_Click(sender As Object, e As EventArgs) Handles ValueSourceAvailabilityBindingNavigatorSaveItem.Click
Me.Validate()
Me.ValueSourceAvailabilityBindingSource.EndEdit()
Me.TableAdapterManager.UpdateAll(Me.ValueTrackerDataSet)
End Sub
Private Sub Form3_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'ValueTrackerDataSet3.SA_CountryCode' table. You can move, or remove it, as needed.
Me.SA_CountryCodeTableAdapter.Fill(Me.ValueTrackerDataSet3.SA_CountryCode)
'TODO: This line of code loads data into the 'ValueTrackerDataSet2.SA_Client' table. You can move, or remove it, as needed.
Me.SA_ClientTableAdapter.Fill(Me.ValueTrackerDataSet2.SA_Client)
'TODO: This line of code loads data into the 'ValueTrackerDataSet1.Cubes' table. You can move, or remove it, as needed.
Me.CubesTableAdapter.Fill(Me.ValueTrackerDataSet1.Cubes)
'TODO: This line of code loads data into the 'ValueTrackerDataSet.ValueSourceAvailability' table. You can move, or remove it, as needed.
Me.ValueSourceAvailabilityTableAdapter.Fill(Me.ValueTrackerDataSet.ValueSourceAvailability)
End Sub
Private Sub ClientIDComboBox_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ClientIDComboBox.SelectedIndexChanged
SELECT *
FROM dbo.SA_Client
ORDER by ClientName
End Sub
End Class
You can't just put a SQL statement inside of a VB .Net sub like that. You need to either use LINQ/Entity Framework, or format the query as a string and send it to SQL. The first method would depend on how your entity is set up, while the second method would look something like this:
'The SQL Connection
Dim sqlLConn As New SqlConnection()
'The SQL Command
Dim sqlCmd As New SqlCommand()
'Set the Connection String
sqlConn.ConnectionString = "connection string goes here"
'Open the connection
sqlConn.Open
'Set the Connection to use with the SQL Command
sqlCmd.Connection = SQLConn
' Set your query
sqlCmd.CommandText = "SELECT * FROM dbo.SA_Client ORDER by ClientName"
' DO STUFF WITH THE sqlCmd query here...
'Close the connection
sqlConn.Close()
First option: You can do it programatically by your sql Query
SELECT * FROM tableName ORDER BY columnName ASC/DESC
second option by settiong the Sorted option to TRUE
Would it solve your problem if the data you retrieved from the database already had the data sorted in ClientName order? In that case, you'll need to change the SQL associated with the Fill method on your SA_ClientTableAdapter data adapter.
If you need to sort the data separately from the DataSet and DataTable, you have a couple of options.
You can use LINQ, and bind to a sorted version of your data. Rather than binding directly to the DataSet or DataTable, you'd bind to an expression:
[whatever you're binding] = Me.ValueTrackerDataSet2.SA_Client.OrderBy(c=>c.ClientName)
You can use a DataView over the DataTable, which is (one of) the older ways we used to do this:
Dim dv as DataView = New DataView(Me.ValueTrackerDataSet2.SA_Client, "", "ClientName", DataViewRowState.CurrentRows)
[whatever you're binding] = dv

Query Access Visual Basic

I am trying to figure out how to query an access db using visual basic but I'm looking for a little explanation on how this actually works.
What I'm confused about is that I state a command SELECT * FROM PI (PI Being the table) but then directly below that, I'm saying that TextBox1.Text = theDataTable.Rows(0).Item(1).
I'm just wondering why I have a query command and then a seperate command that is going to a specified Row and Item....any help is much appreciated!
Imports System.Data.OleDb
Public Class Form1
Dim theConnectionString As New OleDbConnection
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
txtSQL.Clear()
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
theConnectionString.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\Marc Wilson\Documents\FiddleFuckDB.accdb"
theConnectionString.Open()
Dim theDataSet As New DataSet
Dim theDataTable As New DataTable
theDataSet.Tables.Add(theDataTable)
Dim theDataAdapter As New OleDbDataAdapter
theDataAdapter = New OleDbDataAdapter("SELECT * FROM PI", theConnectionString)
theDataAdapter.Fill(theDataTable)
TextBox1.Text = theDataTable.Rows(0).Item(1)
theConnectionString.Close()
End Sub
End Class
Like this
"SELECT * FROM PI Where FieldName = '" & TextBox1.Text & "'"
assumed that your field type is not numeric
Since you're using an ADO.NET DataTable - that object consist of Rows collection and each row in turn consists of Items collection. So in order to get to a specific value you need to use
Table.Rows(X)(Y)
notation. Even if your query returns a single value - you would use this approach. Looking at your code and Items(1) especially, it looks like your query returns at least 2 columns.
If you're interested in a single value only, consider specifying a single column name in your query, make sure that it returns a single row (e.g. by adding WHERE clause to your query) and use ExecuteScalar ADO.NET command, which, unlike Fill and DataTable returns a single value only.
Not 100% sure I undertand the question, but hopefully this helps:
The query command is fetching all of the records from the table in your database. The Rows() and Item() methods fetch a particular field from a particular record (in this case, the second field of the first record).
The Text property of your TextBox cannot display the entire table on it's own: the DataTable is a fairly complicated data strucutre. TextBoxes require a string (or something like one).
SELECT * FROM PI tells the database engine which data it should retrieve from the underlying database table that exists on-disk.
You're using the DataTable class which represents data in-memory: the DataAdapter class reads data from disk (using the SQL statement) and copies it into memory, where you then use the Rows(0).Item(1) command to get a copy of the data already in memory.
The alternative is to use DataReader which is more direct, often simpler. In your case I don't see why you're using the DataTable class because DataReader will suit you fine.