VB.NET and MS Access - Binding (Data won't save to database) - database

I have linked one of my VB.net forms to an MS Access database table, However, when I save the data entered from the VB form into the data set, the data will show in the data set but it will not appear in my database table. Is there anyway I can get the data that I have stored in the data set to appear in the actual database.
I have bound the form fields correctly to the database table and I have added the tables to the form via a data grid.
![Form & Data grid][1]
Can anyone tell me why it won't save to my database? or does anyone have an alternative method for binding forms to a database.
*Note - My database also has a password on it (don't know if that effects it)
*Note - I'm new to this forum so i cant post an image...
*Note - Let me know if you need to see more code
Form loading code
Public Class CD_FORM
Private Sub CD_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'CDKingsDatabaseDataSet.CD' table. You can move, or remove it, as needed.
Me.CDTableAdapter.Fill(Me.CDKingsDatabaseDataSet.CD)
End Sub
ADD Button code
Private Sub Button5_Click(sender As System.Object, e As System.EventArgs) Handles add.Click
CDBindingSource.AddNew()
End Sub
SAVE Button code
Private Sub Button6_Click(sender As System.Object, e As System.EventArgs) Handles sav.Click
CDBindingSource.EndEdit()
CDTableAdapter.Update(CDKingsDatabaseDataSet.CD)
End Sub

Ah Ok I've found the solution thanks to a comment by jmcilhinney on the "VB.NET - .accdb database not saving changes" question made a while back.
The changes to my database have been made but the database I was looking at was in the wrong location.
The database which stored the changes was in my bin/Debug folder.

Related

Calling selection from Combo box on form to be used in SQL query

I have been able to figure out how to populate my combo box with information pulled from a SQL query. What I need to do now is take the item selected from that combo box and run another query with that info using a button. This is what I have so far.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim myconn As New SqlClient.SqlConnection("server=myserver;UID=User;PWD=Password;database=myDB")
Dim myTable As New DataTable()
Dim myCmd As New SqlCommand()
Dim myAdapter As New SqlDataAdapter(myCmd)
myCmd.Connection = myconn
myCmd.Connection.Open()
myCmd.CommandText = "UPDATE myDB.<*Selected list from combo box*> SET example = x WHERE example = y"
myCmd.ExecuteNonQuery()
myCmd.Connection.Close()
MsgBox("Done!")
End Sub
As you can see the issue is the portion I have named <Selected list from combo box> I am not asking for answers on how to do this, I am asking that you all point me in the right direction if possible.
If I understand your question, I believe all you need to do is build a string for your update statement to concatenate the table name in. Something like this would be functional:
myCmd.CommandText = "UPDATE myDB." & listbox1.SelectedItem.Value & " SET example = x WHERE example = y"
One important thing you want to keep in mind though is that a bad value in your list box could cause you to a security vulnerability called SQL Injection. So within your button procedure you might want to do some validation checks to be absolutely sure that the value in listbox1.SelectedItem.Value is strictly a valid table name that you allow to be updated before just passing it along as a SQL command.

VB.net deleting a record but stills shows in database access file

I have created a database file in MS access and linked to vb.net form. When i delete a record at run time it shows deleted in user interface but when i checked the Database file its stills in DB file what should i do ?
I have used this function
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
StudentData1BindingSource.RemoveCurrent()
End Sub
Try saving after you remove the record. Should look something like this:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
StudentData1BindingSource.RemoveCurrent()
Me.Validate()
Me.StudentData1BindingSource.EndEdit()
Me.TableAdapterManager.UpdateAll(Me.StudentData1DataSet)
End Sub

How to determine if a database has been altered for Access, SQL, Oracle or File Systems

At the company I work for all applications pull information from that database, I have decided to write a detailed answer to answer how different databases can let the user know they have been altered. I will answer for the following types:
Access
SQL
Oracle
File systems (Files and folders)
Why I have done this?...... The company I work for have many different databases and applications that use these databases. However the applications spend a lot of time within the database checking to see if the data has been changed. I have complied this list to show how certain databases/files can use different tools to let an application know it has been changed. So an event can be fired off. This will hopefully reduce computing power and speed up the applications.
Please edit as you seem fit. If you need any other information a comment would be great. I am still in the process of adding the Oracle database solution and editing the Access and SQL.
Access and FileSystems/Files
For the access point I have used a SystemFileWatcher. This keeps an eye on the database and if it has been modified it will run the code to get the new data from the database. This means that the application is not constantly going in to the database and grabbing new data when it is not needed.
The FileSystemWatcher can run different code from the events such as name changed, moved or modified. I only need to use the modified. I have got the database path from an XML File I am using which means it is not hard coded and can be changed from the xml file and the watcher will watch else where.
Protected Overrides Sub OnStart(ByVal args() As String)
Dim g1 As New FileSystemWatcher()
g1.Path = GetSingleNode(XmlFileName, "data/G1Path")
g1.NotifyFilter = (NotifyFilters.LastAccess Or NotifyFilters.LastWrite Or NotifyFilters.FileName Or NotifyFilters.DirectoryName)
g1.Filter = GetSingleNode(XmlFileName, "data/G1Filter")
AddHandler g1.Changed, AddressOf OnChanged
g1.EnableRaisingEvents = True
Dim g2 As New FileSystemWatcher()
g2.Path = GetSingleNode(XmlFileName, "data/G2Path")
g2.NotifyFilter = (NotifyFilters.LastAccess Or NotifyFilters.LastWrite Or NotifyFilters.FileName Or NotifyFilters.DirectoryName)
g2.Filter = GetSingleNode(XmlFileName, "data/G2Filter")
AddHandler g2.Changed, AddressOf OnChanged
g2.EnableRaisingEvents = True
End Sub
Protected Overrides Sub OnStop()
End Sub
Public Shared Function GetSingleNode(ByVal xmlPath As String, ByVal nodeLocation As String) As String
Try
Dim xpathDoc As New XPathDocument(xmlPath) 'gets the nodes from the XML file ready to be put in to the network path/variables
Dim xmlNav As XPathNavigator = xpathDoc.CreateNavigator()
Return xmlNav.SelectSingleNode(nodeLocation).Value
Catch ex As Exception
Throw
End Try
End Function
After this I simply have an on changed function. Hope this helps anyone that needs it.
FileSystems/Files
For the file path and system paths the code above is very similar just using different paths and filters to get the certain types or names of files. This will then run the code if these have been changed/modified. If anybody would like code for this please write a comment and I can supply some.
SQL Databases
In the SQL databases there are multiple ways of checking to see if the data has been changed. I will reference a few MSDN Pages along with another question to provide information to these. However the way I used was slightly different as I didn't have a service broker running and no queues were enabled on my SQL databases.
Is there something like the FileSystemWatcher for Sql Server Tables?
http://msdn.microsoft.com/en-us/library/62xk7953.aspx#Y342
However the way I used was by using a checksum and a timer and checking the checksum on a loop to see if the database was changed. As the 'hash' always changes if the data is changed:
http://sqlserverplanet.com/design/how-to-detect-table-changes
http://www.mssqltips.com/sqlservertip/1023/checksum-functions-in-sql-server-2005/
My Code:
'Within main to get the first checksum value ready to be comapred with at a later date. These are global variables
Dim newdata As DataTable = SQLMethods.ExecuteReader(ConnectionString1, "SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM Alarms")
checksum = newdata.Rows(0).Item(0)
Timer1.Start()
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Timer1.Stop()
Dim newdata As DataTable = SQLMethods.ExecuteReader(ConnectionString1, "SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM Alarms")
checksumNew = newdata.Rows(0).Item(0)
If checksum <> checksumNew Then
MsgBox("Hello")
checksum = checksumNew
End If
Timer1.Start()
End Sub
As you can see if they do match the checksum is changed to match so the next time it happens they will be the same unless the database is indeed changed. I have stopped and then restarted the time to avoid confusion of the message box, however the message box is used for debugging purposes as an event could be fired here or what ever code was wanting to happen if the database was changed.
Oracle
After doing research I have not been able to implement this solution in my own application but hopefully it will provide info to other users. In Oracle there is something called OracleDependencyClass which provides an application a notification if the chosen data has been modified. I will supply some hyper-links that have some examples and the basics of how to use these in the hope someone doesn't need to mirror my own research.
Developing Applications with Database Change Notification
OracleDependency Class
Oracle® Data Provider for .NET Developer's Guide - OracleDependency Class(2)
Example of using the class in C# and VB.NET
If these pages don't help there are plenty of other webpages that you can access if you either search for "oracle dependency", "OracleDependency Class" and "Database Change Notification".

Trouble reading database records into memory variables in VB 2010

I followed an example on stackoverflow about how to read database records into variables. This is the first time doing this and I feel that I'm close but I'm baffled at this point about the problem.
Here is the link I am referring to:
Visual Basic 2010 DataSet
My code is shown below.
Public Class Form1
' DataSet/DataTable variables
Dim testdataDataSet As New DataSet
Dim dttestdataDataTable As New DataTable
Dim datestdataDataAdapter As New Odbc.OdbcDataAdapter
' Variables for retrieved data
' Dim sSpeed As String = ""
' Dim sFuelprice As String = ""
Dim sSpeed As Integer
Dim sFuelprice As Integer
'Connect to the database
''
'Fill DataSet and assign to DataTable
datestdataDataAdapter.Fill(TestdataDataSet , "TestdataDataSet")
dttestdataDataTable = TestdataDataSet.Tables(0)
'Extract data from DataTable
' Rows is the row of the datatable, item is the column
sSpeed = dtTestdataDataTable.Rows(0).Item(0).ToString
sFuelprice = dtTestdataDataTable.Rows(0).Item(1).ToString
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
result.Text = Val(miles.Text) * sSpeed * sFuelprice
End Sub
End Class
Basically, I am getting declaration errors and I don't understand why since the example I was following clearly declared them. I'm connecting to an Access DB called "testdata.mdb" which contains only 1 record with two fields that I want to use throughout the program. The exanple said to dim the variables for each field as strings but this created more dim errors so I made them into integers and remarked out the original dim statements in the meantime (since they're going to be used in calculations.) The dataadapter and datatable variables also are getting flagged for not being declared when they were earlier in the program. I know this must be a simple thing to fix but I'm just not seeing it.
The form is just a simple thing where the user types in a number and a result is produced by using the numbers read in from the database. In short, I want to be able to do simple calculations with a database within a program and the dim statement thing is getting in the way.
If someone can please clarify what I should do, that would be very much appreciated. Thanks!
When you're trying to learn new technology, it's usually best to work from the outside in. The "outside-most" object in your case seems to be an OdbcConnection object.
Public Class Form1
Const connectionString as String = "Driver={Microsoft Access Driver (*.mdb)};DBQ=c:\bin\Northwind.mdb"
Dim connection As New OdbcConnection(connectionString)
connection.Open()
connection.Close()
end Class
Resolve errors at that level first. Then add a declaration for the data adapter--only for the data adapter--and resolve any errors with that. Repeat until you finish your class.
See OdbcConnectionString, and refer to the connection string web site if you need to.
I apologize for the delay in writing the answer to close off this question and sum it up.
In my case, it dataset is a one row database called testdata and contains 20 fields.
The solution that worked is as follows:
Immediately after the form1_load event, the variables can be immediately written after the dataadapter line:
Me.TestdataTableAdapter.Fill(Me.fooDataSet.testdata)
speed = Me.fooDataSet.testdata(0).speed
fuelprice = Me.fooDataSet.testdata(0).fuelprice
mpg = Me.fooDataSet.testdata(0).mpg
Then just DIM the variables to whatever you want them to be (in this case, speed is an integer, fuelprice is a decimal and MPG is a decimal) right after the PUBLIC CLASS statement at the top of your form's code.
You can then manipulate the variables in calculations after a button click as such:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
fuelcost = CDec((miles.Text/ mpg) * fuelprice)
txtfuelcost.Text = fuelcost.ToString
End Sub
Thank you all for your responses!

ADO.NET: Need help to understand the basics of 'Dataset'

As context, I am new to ADO.NET and have been using 'Programming ADO.NET 2.0' by David Sceppa to help build my knowledge.
I have been trying to understand the Dataset object but think I may have completely misunderstood the point and am looking for guidance.
As an example, I have built a really simple Form with a combobox with an aim of filling the combobox with the names of people in a database ("MyDatabase"). The following code works fine for me:
Private Sub frmEmployee_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim strConn, strSQL As String
strConn = "Data Source=.\SQLExpress;Initial Catalog=MyDatabase;Integrated Security=True;"
strSQL = "SELECT LastName, FirstName FROM EmployeeTable"
Dim da As New SqlDataAdapter(strSQL, strConn)
Dim ds As New DataSet()
da.Fill(ds, "AllEmployeesList")
For i As Integer = 0 To ds.Tables("AllEmployeesList").Rows.Count - 1
Dim row As DataRow = ds.Tables("AllEmployeesList").Rows(i)
cbAllEmployeesList.Items.Add(row("LastName") & ", " & row("FirstName"))
Next
End Sub
Now suppose I have a button on my Form ('GetAge') which is designed to retrieve the age of the employee selected in the combobox from the dataset "AllEmployeesList" and display in a TextBox on the same Form.
The bit I really don't understand is how I can interact with the original dataset that I have created to get the age? It seems to me that the dataset is only in memory during the Load event? If my dataset persists beyond the Load event then where can I find it?
My understanding is that a dataset object is an offline cache of data and has no links to the underlying database.This is useful as it allows you to manipulate the data without keeping a connection open and later on you can submit any changes in the Dataset back to the original database. So once I have built my dataset in the Load event how can I then further interact with it?
I suspect there is a large error in my understanding of what a Dataset object is. Can anybody set me straight?
Thanks to anybody who can help
Alex
A data set can hold multiple data tables, so if you fill that same dataset that already has the "AllEmployeesList" datatable filled, you can fill another datatable with the age under another table name. Picture a dataset as an in-memory database.
You can store the dataset in the datasource of the datagrid view, or make it a form level variable so you can interact with it without casting anytime.
Another part of datasets to be aware of is you can make a design-time dataset so things are more type-safe and explicit.
You seem to have a good grasp on the concept and reason of the DataSet. Your question is really more about managing state than the ins and outs of a DataSet.
You never stated if you are using WebForms, WinForms, or something else. If you're using WinForms, promote the DataSet to be a member variable of the form. It'll stay in memory as long as the form is open.
If you're using WebForms, then this becomes much more complex. This is a good overview to get you started.
Unless your application needs to operate in a disconnected mode, it's not strictly necessary nor always a good idea to cache database data on the client. In this case, you're extracting the age data for all employees without knowing whether you'll ever need it for any of them.
I would just pull the first and last name data (probably using SqlCommand.ExecuteReader) to populate the list box, and then make a separate call to the database to get the age if the user clicks the button. I posted an example of something similar using SqlCommand.ExecuteScalar on your other question.
When a Function or Sub has finished executing, all the variables you declared with the Dim statement will be gone. If you want a variable to exist as long as your form exists then declare a variable outside your Sub/Function:
Public Class frmEmployee
Private dsEmployeeList As DataSet
Private Sub frmEmployee_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
...
dsEmployeeList = New DataSet()
da.Fill(dsEmployeeList, "AllEmployeesList")
...
End Sub
Private Sub GetAge_Click(sender As Object, e As EventArgs) Handles GetAge.Click
Dim iRowIndex As Integer
iRowIndex = cbAllEmployeesList.SelectedIndex 'In this case the rownumber is the same as the index of the selected item in the combobox
'Check to see if an item from the combobox has been selected
If iRowIndex >= 0 Then
txtEmployeeAge.Text = dsEmployeeList.Tables("AllEmployeesList").Rows(iRowIndex).Item("Age").ToString()
End If
End Sub
This code might work but it's not a recommended solution. Like the previous poster said: only get the data you want, when you need it.
You should bind the DataGrid to the DataSet. When reqd you can retrieve the DataSet back from the DataGrid.DataSource and cast it to a DataSet.
Edit: Added sample code
DataSet ds = new DataSet();
// Code to populate DataSet from your DB
...
...
Assign ds to the datasource of data grid
this.dataGridView1.DataSource = ds;
To retrieve the dataset use the code below
DataSet retrievedFromGrid = (DataSet)this.dataGridView1.DataSource;
However, if you need to perform operations on this DataSet a number of times and memory is not an issue, I would suggest you store it in a class variable to avoid the overhead of casting in a DataSet object from the DataGrid again and again.

Resources