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

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.

Related

Data retrieval from Access file into DataTable not working

I have some code to connect a database with the program, but for some reason at run time it does not show the data from the DB.
Public Class Form2
Dim con As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\employee\employee.accdb")
Dim cmd As New OleDbCommand("", con)
Dim empDA As New OleDbDataAdapter
Dim empTable As New DataTable
Dim dr As OleDbDataReader
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.EmpTableAdapter.Fill(Me.EmpDataSet.emp)
Dim cmd As New OleDbCommand("select * from emp", con)
empDA = New OleDbDataAdapter("select * from emp", con)
empDA.Fill(empTable)
DataGridView1.DataSource = empDA
End Sub
The code in the question looks to be a bit muddled as to what needs to be done.
Variables should be limited to the minimum scope that they are needed in, and some things need to be disposed of after use (to avoid memory leaks, files remaining locked, and other problems with computer resources).
For the disposal, the Using statement is useful as it makes sure that that is done automatically.
You should try to put each logical piece of code in a suitably small method so that it is easier to work with. Perhaps something like this:
Imports System.Data.OleDb
Public Class Form2
Dim connStr As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\temp\employee.accdb"
Sub ShowEmployeeData()
Dim sql = "SELECT [Id], [FirstName] FROM [Employees] ORDER BY [Id]"
Using conn As New OleDbConnection(connStr)
Using cmd As New OleDbCommand(sql, conn)
Dim employees As New DataTable()
Dim da As New OleDbDataAdapter(cmd)
da.Fill(employees)
DataGridView1.DataSource = employees
End Using
End Using
End Sub
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ShowEmployeeData()
End Sub
End Class
So the connStr variable is available everywhere in the class Form2, and the code that shows the employee data is in its own Sub.
When querying a database, you should specify the actual columns that you need, so that the columns are returned in the order you want, and order by one of the columns so that the data is returned in a predicatable order - databases are free to give you any order for anything if you don't tell them otherwise.
Ok, while you have some tips and suggestions, I'll give a few more.
First, try using the project setting to create the connection. The reason for this is not only can you create + test + make a connection, you can do this without code.
so, try this to build + create the connection:
so now click on the [...] and it will launch the connection builder for you!
So you now get this:
(use the change button if it defaulted to sql server).
So, using the above allows you to build ONE connection - one that you can use for the WHOLE application.
And there is the handy test connection button!!
So, in above we called the connection "MyDB".
That way we don't have messy connection strings in code, and we have ONE place to change/set the connection.
Now, in code?
Well, as a really nice tip?
You often need a connection
You often need a data reader.
and you need some sql (command text).
So, in place of declaring that reader, declaring the conneciton, and all that jazz?
use a command object!
Why?
because the command object has ALL of the above 3 objects in one nice simple ONE object.
As a result, you don't have to declare the 3 separate objects.
Just use and adopt a command object in MOST cases.
So, now our code has this:
Imports System.Data.OleDb
Public Class DataGridTest1
Private Sub DataGridTest1_Load(sender As Object, e As EventArgs) Handles Me.Load
Using cmdSQL As New OleDbCommand("SELECT ID, FirstName, LastName, HotelName from tblHotels",
New OleDbConnection(My.Settings.MyDB))
cmdSQL.Connection.Open()
Dim rstData As New DataTable
rstData.Load(cmdSQL.ExecuteReader)
DataGridView1.DataSource = rstData
End Using
End Sub
End Class
Note how simple - and how few variables we have to setup and declare.
So, I find this becomes quite much as easy as using Access or even writing older VB6 code.
So, try the above - its very little code, and use the connection builder in the "settings" for the application - thus removing the need to introduce connection strings all over the place in code.

populate a sql query into datagridview on vb.net

I wanna populate sql query on datagridview on vb.net
I tried this code that I found on internet
but I get an error
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
DataGridView2.Visible = False
Dim Dataconnection As SqlConnection
Dataconnection.ConnectionString = "server=DESKTOP-514KV5J\SQLEXPRESS;database=A;trusted_connection=True"
Dim cmd As New SqlCommand
cmd.Connection = Dataconnection
cmd.CommandText = "select SA,Product,sum(quantity) quantity from(select SA,Product,quantity from tbpurchase union all select SA,Product,-quantity from tbsold)dt group by SA,Product"
Dim rdr As SqlDataAdapter = cmd.ExecuteReader
Dim dt As New DataTable
dt.Load(rdr)
rdr.close()
DataGridView2.DataSource = dt
End Sub
I just want to view the query on datagridview2 whitout any storage on any table .
if you have a solution how can I do it .
because i have 2 tables .
1 for purchasing .
1 for selling.
and the query that i did work on ms sql well and caculates the stock still available
thanks in advance
There are two obvious issues there and, for all we know, there could be more. Firstly, you never actually create a connection object. All you do is declare a variable and then try to set the ConnectionString of an object that you never created. That's absolute programming fundamentals and nothing specific to do with data access, so that's not something we should have to explain, especially since you are creating objects later in the code so obviously know how.
Secondly, you aren't even trying to open the connection that you didn't create. If you call Fill on a data adapter then it will open and close the connection automatically but, if you use a data reader, you have to do it yourself.
With those two issues in mind and cleaning up the code somewhat, we arrive at this:
Using connection As New SqlConnection("server=DESKTOP-514KV5J\SQLEXPRESS;database=A;trusted_connection=True"),
command As New SqlCommand("SELECT SA, Product, SUM(Quantity) Quantity FROM (SELECT SA, Product, Quantity FROM tbpurchase UNION ALL SELECT SA, Product, -Quantity FROM tbsold) dt GROUP BY SA, Product", connection)
connection.Open()
Dim table As New DataTable
Using reader = command.ExecuteReader()
table.Load(reader)
End Using
DataGridView2.DataSource = table
End Using
For objects that support it, you should always create them with a Using block if you are only going to use them then and there, because they will be implicitly disposed at the End Using line. It is also preferable to pass arguments to constructors rather than call parameterless constructors and then set properties immediately after.

CommandText Property Has Not Been Initialized, retrieving data

Private Sub ButtonSubmitID_Click(sender As Object, e As EventArgs) Handles ButtonSubmitID.Click
Dim comm As New SqlCommand
Dim conn As New SqlConnection
conn.ConnectionString = "Data Source = localhost\SQLEXPRESS; Initial Catalog = test2Forms; Integrated Security = SSPI;"
comm.Connection = conn
Dim ID = TextBoxID.Text
comm.Parameters.AddWithValue("#ID", ID)
Dim adapter As SqlDataAdapter = New SqlDataAdapter(comm.CommandText, comm.Connection)
comm.CommandText = "SELECT * FROM withActivityLog3 WHERE ID = #ID"
Dim records As DataSet = New DataSet
adapter.Fill(records)
DataGridView2.DataSource = records
End Sub
CommandText property has not been initialized is the error I am receiving. I am able to pull all the data from the database into the GridView on the Form Load but when I try to narrow it down to one ID using a WHERE clause on the button trigger, it comes up with the above error. I've used the debugger to trace through one step at a time and the command and connection strings look correct. I've also successfully duplicated the query on my database using the SQL Server command line. I'm searching on a primary key (ID) so the expected results would be one uniquely identified row from the database.
As for the problem you know you have:
' initialize DataAdapter with (EMPTY) commandtext
Dim adapter As SqlDataAdapter = New SqlDataAdapter(comm.CommandText, comm.Connection)
' initialize Command Text
comm.CommandText = "SELECT * FROM withActivityLog3 WHERE ID = #ID"
When you pass the CommandText to the DataAdapter, it is empty because you havent set it yet which results in the error.
There is a fair amount of inefficiency in your code though. Rewritten:
' form level conn string
Private TheConnString As String = "Data Source = localhost\..."
Private Sub ButtonSubmitID_Click(sender ...
Dim dt As New DataTable
Using dbcon As New MySqlConnection(TheConnString)
Using cmd As New MySqlCommand("select * from Sample where Id = #id", dbcon)
cmd.Parameters.Add("#id", MySqlDbType.Int32).Value = Convert.ToInt32(TextBox2.Text)
dbcon.Open()
dt.Load(cmd.ExecuteReader)
dgvA.DataSource = dt
End Using
End Using
End Sub
Note: this uses MySQL but the concepts are the same for Sqlite, Access, SQL Server etc
There is no need to type or paste the connection string and over everywhere it is used. One form level variable will allow DRY (Dont Repeat Yourself) code.
Anything which implements the Dispose() method should be disposed of. That includes nearly all the DB Provider objects. The Using statement allows you to declare and initialize an object and at the End Using it is disposed of. Failing to Dispose of things can cause leaks and even run out of connections or resources to create things like DB Command objects.
There is no need to create a local DbDataAdapter. These are very powerful and useful critters meant to do much more than fill a DataTable. If that is all you are doing, you can use ExecuteReader method on the DbCommand object.
Nor do you need a local DataSet. Contrary to the name, these do not hold data, but DataTables. Since there is only one and it is local (goes out of scope when the method ends), you dont need a DataSet to store it.
The Add method should be used rather than AddWithValue. The code above specifies the datatype for the parameter so there is no guesswork required of the compiler. Of course with that comes the need to convert the text to a number...
...Since this is user input, you should not trust the user, so Integer.Tryparse would be more appropriate: I like pie will not convert to an integer. Data Validation is something you should do before you commence the DB ops.
Dim ID = TextBoxID.Text as used is pointless code. You do not need to move the textbox text into a new variable in order to use it. However, ID might be used to store the integer value

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.

update requires a valid updatecommand when passed datarow collection with modified rows

Am trying to update the access database with the values in the datagrid by the following command:
Private Sub btnUpdate_Click(ByVal source As Object, ByVal e As EventArgs) Handles btnUpdate.Click
Dim conn As New OleDbConnection(Con)
Dim bsource As BindingSource = New BindingSource()
Dim da As New OleDbDataAdapter
Dim dt As DataTable = ds.Tables("Config_access")
Me.DataGridView1.BindingContext(dt).EndCurrentEdit()
Me.da.Update(dt)
MsgBox("Table Updated")
End Sub
I am facing the error mentioned in the subjectline. Please suggest.
There are a few pieces you have missing. You need a command object and an update command for your data adapter. You'll need to know how to write an update SQL statement. It is suggested you use parameters to identify which row you want to update. Maybe your table has some sort of unique id field (Primary Key)? You can include some of the table information in your question to get feedback on how to do that.
You can start here to address the command error. If you run into other errors, you may want to repost.