I am doing a small system using Ms. Access (the database has more than 10 tables ) connecting to visual studio. I made a public class for opening the connection to the database so I can use it in every form. Everything is working and I can get the data from the database But any inserting or deleting data in forms, the database in ms access not getting the update. I can see the new records in forms but nothing in the database.
Imports System.Data.OleDb
Public Class dbconnectClass1
'create db connection
Private DBcon As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0; Data Source=dental_clinic.accdb;")
'prepare db command
Private dbcmd As OleDbCommand
' db data
Public DBDA As OleDbDataAdapter
Public DBDT As DataTable
'query parameters
Public params As New List(Of OleDbParameter)
'query statics
Public recordcount As Integer
Public Exception As String
Public Sub ExecQuery(query As String)
'reset query status
recordcount = 0
Exception = ""
Try
'open connection
DBcon.Open()
'create db command
dbcmd = New OleDbCommand(query, DBcon)
'load params into dbcommand
params.ForEach(Sub(p) dbcmd.Parameters.Add(p))
'clear params list
params.Clear()
'excute command and fill dataset
DBDT = New DataTable
DBDA = New OleDbDataAdapter(dbcmd)
recordcount = DBDA.Fill(DBDT)
Catch ex As Exception
Exception = ex.Message
End Try
'close the database connection
If DBcon.State = ConnectionState.Open Then DBcon.Close()
End Sub
'include query and command parameters
Public Sub addparam(name As String, value As Object)
Dim newparam As New OleDbParameter(name, value)
params.Add(newparam)
End Sub
End Class
This my code inside the forms:
Public Class NewExpense
Private access As New dbconnectClass1
' a varuble having the appointment Id to connect between 2 forms
Private appointmentNo As Integer
Private Function NoError(Optional report As Boolean = False) As Boolean
If Not String.IsNullOrEmpty(access.Exception) Then
If report = True Then MsgBox(access.Exception)
Return False
Else
Return True
End If
End Function
Private Sub Savebuttum_Click(sender As Object, e As EventArgs) Handles
Savebuttum.Click
Dim oDate As DateTime = Convert.ToDateTime(DateTimePicker1.Value)
access.addparam("#expensenme", expensenmtXT.Text)
access.addparam("#expensedetail", ExpenseDetailTXT.Text)
access.addparam("#expenseamount", ExpenseAmountTXT.Text)
access.addparam("#expensedate", oDate)
access.addparam("#expensepaidTo", paidtoTXT.Text)
access.ExecQuery("INSERT INTO Expense (Expenses_name, expense_details,
expenses_amount, ExpenseDate_Paid, ExpensePaid_To) Values (#expensenme,
#expensedetail, #expenseamount, #expensedate, #expensepaidTo);")
'report on errors
If Not String.IsNullOrEmpty(access.Exception) Then
MsgBox(access.Exception) : Exit Sub
'success
access.DBDA.Update(access.DBDT)
MsgBox("Expense Has been Added Successfully")
End Sub
End Class
Hum, you have this:
params.ForEach(Sub(p) dbcmd.Parameters.Add(p))
Great, we add the parmaters - looks good to go!!!
then, next line CLEARS all the work above!!! (the parameters are removed!!!!)
'clear params list
params.Clear()
Next up? Many will build a connection object, then a reader, and then a adaptor. But you ONLY need a data adaptor if you going to update a data table. if you just going to execute a command, then you don't need the data table, and you don't need a adaptor FOR that table. Adaptor = ability to modify a existing datatable (or dataset).
You are MUCH better to use the command object.
Why?
Because the command object has a connection object (don't need a separate one)
Because the command object has a data reader for you (no need for a whole data adaptor to JUST fill a table. And remember, you don't need a whole data adaptor UNLESS you are going to send/update a data table back to the database.
And because the command object has the command text, then you don't even need a variable for that!!!
And because all objects are in "one object", then really all you need is something to handy get you the connection.
So, for your insert example, we really don't gain by having that object, do we?
Ok, so here is your insert code without using those extra objects:
so in the following, I declare ONE variable, - the sql command object.
And do the insert
And as FYI? Your save button is not a save - but a insert button - every time you hit it, you will insert a new row. Lets deal with that issue in a bit.
So, here is our code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Using cmdSQL As New OleDbCommand("INSERT INTO Expense
(Expenses_name, expense_details,expenses_amount, ExpenseDate_Paid, ExpensePaid_To)
Values (#expensenme,#expensedetail, #expenseamount, #expensedate, #expensepaidTo)",
New OleDbConnection(My.Settings.TESTOLEDB))
With cmdSQL.Parameters
.Add("#expensenme", OleDbType.WChar).Value = expensenmtXT.Text
.Add("#expensedetail", OleDbType.WChar).Value = ExpenseDetailTXT.Text
.Add("#expenseamount", OleDbType.Currency).Value = ExpenseAmountTXT.Text
.Add("#expensedate", OleDbType.DBDate).Value = DateTimePicker1.Value
.Add("#expensepaidTo", OleDbType.WChar).Value = paidtoTXT.Text
End With
cmdSQL.Connection.Open()
cmdSQL.ExecuteNonQuery()
End Using
So things in above:
We have strong data typing and converstion.
Because of this, note how I did NOT have to create a separate date/time variable here.
Note the SAME for "money" or so called currency conversion - again strong data type by using parameters this way.
And is this a date only, or a date+ time value? If it is date, then
.Add("#expensedate", OleDbType.DBDate).Value = DateTimePicker1.Value
If it was/is a date + time, then this:
.Add("#expensedate", OleDbType.DBTimeStamp).Value = DateTimePicker1.Value
So, notice how all your object stuff REALLY did not help one bit, and in fact you did not really save code, and above actually had LESS variables defined to do the whole job.
Now, back to the insert issue/problem. (you save is doing a insert). But what about editing existing records?
So, I would suggest you work out the problem this way:
You create/get/have/assume a data row for the form.
The form takes the data row, fills the controls. You edit, and when you hit save, the data row is sent back to the datbase. So, once this works, then to add? Well, the add code will CREATE a new data row, save to database and THEN you send that new data row to the above eixsting form that can edit a data row, and can save a data row. So the form now is able to deal with both issues (adding vs editing existing). If the user dont' want the row, then you offer a delete button.
And REALLY nice is a data row means you don't deal with SQL, and don't deal with parmaters!!
So the code (desing pattern) I use is thus this:
dim da as oledbDataAdaptor
dim myTable as DataTable = MyRstEdit("SELECT * from tblHotels WHERE ID = " & lngID,da)
dim MyDataRow as DataRow = myTable.Rows(0)
' code to fill controls
txtHotelName.Text = MyDataRow("HotelName")
txtCity.Text = MyDataRow("City")
' etc. etc. etc.
Now to save? Well I put the values back into that DataRow like this:
MyDataRow("HotelName") = txtHotelName.Text
MyDataRow("City") = txtCity.Text
MyDateRow("BookingDate") = txtTimePick1.Value
da.Update(MyTable)
Notice how I don't have parameters, and even strong data type checking occurs for say the above Date/Time booking date column.
And the above is nice, since I don't have to deal with ANY parmaters to udpate a row of data.
The MyRstEdit routine looks like this and returns byREf a "da" (data adaptor).
Public Function MyrstEdit(strSQL As String, Optional strCon As String = "", Optional ByRef oReader As SqlDataAdapter = Nothing) As DataTable
' Myrstc.Rows(0)
' this also allows one to pass custom connection string - if not passed, then default
' same as MyRst, but allows one to "edit" the reocrdset, and add to reocrdset and then commit the update.
If strCon = "" Then
strCon = GetConstr()
End If
Dim mycon As New SqlConnection(strCon)
oReader = New SqlDataAdapter(strSQL, mycon)
Dim rstData As New DataTable
Dim cmdBuilder = New SqlCommandBuilder(oReader)
Try
oReader.Fill(rstData)
oReader.AcceptChangesDuringUpdate = True
Catch
End Try
Return rstData
End Function
So, now in vb.net, I actually find it is LESS code then even writing + using recordsets in MS-Access VBA code.
However, BEFORE you go down ANY of the above road?
Have you considered using the vb.net data binding features. Data-binding in vb.net means that you do NOT write ANY of the above code. it means that vb.net will do all of the dirty work, and write and setup ALL OF the code for you to edit data on a form. The end result is you don't write any code to update a table.
You do have to use + create a "data set". Once done, then you just drag controls onto the form, and you even get this. So you just drop in a dataset, table adaptor, Binding navagator, and you get this:
Note now the tool bar at the top (and you can place it on teh bottom if you wish). So you get this:
So that WHOLE form was created without having to write ONE line of code. And you can see we have navigation, edits and saves and even the ability to add. So, you can build up a editing form - and it thus becomes similar to say working in MS-Access and ZERO lines of code is required to build the above form.
However, if you ARE going to roll your own code? Then use a data row. That way you can shuffle data to/from the table, and NOT have to use parmaters and SQL update and insert statements - but ONLY have nice clean code in which you shove, or get values from that data row. .net will "write" all the update stuff for you.
I'm creating a form where I can do the following:
please see the image
As you can see, I have a txt_id_up and txt_id_dw
in the database I want to make the following query.
SELECT * FROM Tabla1
WHERE ID BETWEEN 3 AND 7;
where txt_id_up = 3, and txt_id_dw = 7;
Dim connection As OleDbConnection
Dim command As OleDbCommand
Dim data_reader As OleDbDataReader
'------------------------------
'connect to ms.access database
connection = New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data
Source= data\base.accdb;Persist Security Info=False")
connection.Open()
'reading data from Tabla1 table
command = New OleDbCommand("SELECT * FROM Tabla1", connection)
data_reader = command.ExecuteReader
'----------------------------------
'here the code to show in listview1 is missing
'----------------------------------
and in passing I would like to ask another question, can only the following columns be shown in listview?
Name
Account
I clarify that I use the datagridview to see it in general and the listview for queries
I don't know if I get your question but if you want to display Name and Account from your database I suggest you to use DataGridView.
Add a DataGridView control to your form and add this code:
Dim connection As OleDbConnection
Dim command As OleDbCommand
Dim data_adapter As OleDbDataAdapter
'------------------------------
'connect to ms.access database
connection = New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data
Source= data\base.accdb;Persist Security Info=False")
connection.Open()
'reading data from Tabla1 table
command = New OleDbCommand("SELECT Name, Account FROM Tabla1 WHERE ID BETWEEN 3 AND 7", connection)
data_adapter = New OleDbDataAdapter(command)
'add results to DataGridView1
Dim datatable as New DataTable("Table")
data_adapter.Fill(datatable)
DataGridView1.DataSource = datatable
I may have the 2 text boxes backwards.
Public Class Form3
Private Sub FillListView()
ListView1.BeginUpdate() 'keeps the control from repainting on each addition
Using connection As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data
Source= data\base.accdb;Persist Security Info=False")
Dim command As New OleDbCommand("SELECT ID, Name FROM Tabla1 Where ID Between ? And ?;", connection)
command.Parameters.Add("FirstID", OleDbType.Integer).Value = CInt(txt_id_up.Text)
command.Parameters.Add("SecondID", OleDbType.Integer).Value = CInt(txt_id_dw.Text)
connection.Open() 'Open the connection at the last possible minute
Using data_reader = command.ExecuteReader
While data_reader.Read()
Dim li As New ListViewItem()
li.Text = CStr(data_reader.GetValue(0)) 'ID
li.SubItems.Add(CStr(data_reader.GetValue(1))) 'Name
ListView1.Items.Add(li)
Loop
End Using
End Using
ListView1.EndUpdate()
End Sub
End Class
Edit
The BeginUpdate of the ListView control prevents the screen from
repainting every time you add an item. This speeds up the addition
of items.
The Using...End Using block makes sure your connection is closed and disposed
event if there is an error.
I added question marks in the Where clause of your SQL statement.
These are placeholders for parameters in the Access/OleDb provider.
I added the 2 parameters to the Parameters collection of the Command
object. The Add method has a number of overloads. The one used here
takes a name and data type. Then the Value property of the parameter
is set to the numbers in the text boxes. These values are in a text
property so they are strings and need the CInt() to convert to
Integers.
I moved the Open method to directly before the command is executed.
Again the Using...End Using block as explained above.
OOPS! I forgot to add the loop (red face) - Code is now corrected
Inside the loop, create a new ListViewItem. A new item for each
iteration of the loop.
Set the Text property of the ListViewItem to the first column in the reader. Convert it to a string. This should show up in the first column.
Set the first SubItem of the ListViewItem to the second column of
the reader. Again convert to a string. This should show up in the
second column.
Add the ListViewItem to the ListView.
The first End Using will close and dispose your data_reader. The
second End Using will close and dispose your connection.
Very Important! ListView1.EndUpdate() Nothing shows up in the
ListView without this line.
Hope this helps.
I have a client/server desktop application that I am having some database connection issues with on some of my clients pc's. When I wrote the app, I didn't know any better so I created and opened 1 database connection on application startup, and used that same connection all throughout the app. I know realize this is a bad idea since shaky network connections and it seems antivirus programs are causing these connection to be dropped at times, leading to some errors. I have hundreds of places in code where I need to go back and create/open/close the connection at the time they are being used.
The question is, is there any way to create a public function in which I can do just that, and then do a global find and replace to replace the connection name with the new function name?
something like:
Dim qry As NpgsqlCommand
sqlUpdateItem = "update table set field = value where id = 1"
qry = New NpgsqlCommand(sqlUpdateItem, con)
qry.ExecuteNonQuery()
to
Dim qry As NpgsqlCommand
sqlUpdateItem = "update table set field = value where id = 1"
qry = New NpgsqlCommand(sqlUpdateItem, newCon())
qry.ExecuteNonQuery()
public function newCon()
Dim con As New NpgsqlConnection(connectionString)
con.Open()
Return tcon
End Function
I tried this but no luck. I'm just looking for any possible solutions that don't involve me updating several lines of code in hundreds of places throughout my app. The nice thing is I would only need to do this for all commands, since I can pass a brand new connection into a data adapter and it will handle the opening/closing.
Here's an example of how I'd recommend you attempt it.
Enable option strict in your project. It's better to have your errors at compile time than at runtime.
Use a using statement to safely dispose of the database classes even if you get an exception.
Private _connectionString As String = "blah"
Public Function GetDbConnection() As NpgsqlConnection
Dim con As New NpgsqlConnection(_connectionString)
con.Open()
Return con
End Function
Public Sub DoMyQuery()
Using conn = GetDbConnection()
Using qry = New NpgsqlCommand("update table set field = value where id = 1", conn)
qry.ExecuteNonQuery()
End Using
End Using
End Sub
I apologize if has been asked, and answered somewhere else, but I have been searching like crazy and can't find what I'm looking for.
OleDbConnection^ conn = gcnew OleDbConnection ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Milestone3testdatabase.accdb; Persist Security Info=True");
OleDbCommand^ com = gcnew OleDbCommand();
com->Connection = conn;
com->CommandText = "SELECT *FROM tblcity;";
System::Data::DataSet^ ds = gcnew System::Data::DataSet();
OleDbDataAdapter^ adapt = gcnew OleDbDataAdapter();
adapt->SelectCommand = com;
adapt->Fill(ds,"why");
dataGridView1->DataSource = ds->Tables["why"];
I am trying to figure out how to actually use the data I obtain from the database. I was shown how to put it into a gridview, BUT I don't want a gridview. I want be able to take 1 cell of the table and display it as text.
How do I convert the table into usable data for a C++ forms application?
Either modify your SELECT so that it returns only a single value by using SqlCommand.ExecuteScalar Method or extract the value from your table with the DataTable.Select Method and DataTable.Rows Property
myDataTable->Rows[rowNumber][columnNumber]
I have an windows application. I browse for the file and select the excel file using OpenFileDialog control. The excel file contains email id's in column A. I want to populate the list-box with excel file column values. Office 2003 is installed on my machine. Can somebody Please help me out?
Thanks in Advance.
Refer: Reading Excel files from C#
To connect to an excel file you need the appropriate connection string:
string connString = #"Provider=Microsoft.ACE.OLEDB.12.0; Data Source=<YourExcelPath>;
Extended Properties=\"Excel 12.0;HDR=YES;\"";
After use the OleDb classes to query the information from the file:
string selectCmd = "SELECT * FROM <SheetName>";
using(OleDbConnection excelConn = new OleDbConnection(connString))
{
excelConn.Open();
OleDbCommand command = new OleDbCommand(selectCmd, excelConn);
OleDbDataAdapter da = new OleDbDataAdapter(command);
DataTable sheetInfo = new DataTable();
dataAdapter.Fill(sheetInfo);
//Do something with the data.
Bind your control with this datatable here
}
So you need to replace "YourExcelPath" with the path of your excel file..