Visual Basic Development Bookmark and Share   
 Home > Visual Basic General > Need help to update source database - access
 

Need help to update source database - access

I am developing a VB.Net windows application to replace a legacy Access database. I started with the legacy database (.mdb) and made changed to tables (like deleting unused columns) and changing anniversaries from 3 columns (day, month, and year) to DataTime etc. I recognized the need to import data from the legacy system at the time when the new one goes live and wrote an import dialog to do this. And this is where my problem is. The importer correctly imports the data and writes new tables, but each time I restart the application I have the old data back.

This is the approach I took:

In the load event I fill each tableadapter in the new (target) dataset as follows:

Me.ClientInfoTableAdapter1.Fill(Me.DataSet1.ClientInfo)

I Then populate a TreeView with nodes for each table name in the dataset by iterating the dataset

For Each table As DataTable In DataSet1.Tables

Dim nm As String = table.TableName

TreeView1.Nodes.Add(nm)

Next

The user can choose a legacy database (.mdb file) using an OpenfileDialog, then ticks the tables (in the TreeView) that should be imported and presses the import button.

At this stage my code iterates the Treeview for each checked table name it instantiates a datatable as follows:

‘get a connection string to (source) legacy database

Dim fromConnection As String = GetFromConnection()

DataSet1.EnforceConstraints = False

For Each nd As TreeNode In TreeView1.Nodes

If nd.Checked Then

Dim tbl As DataTable = DataSet1.Tables(nd.Text)

ImportTable(fromConnection, tbl)

Next

DataSet1.EnforceConstraints = True

If tbl.HasErrors Then

‘handle errors

Else

�span style="color:green"> If no errors, AcceptChanges.

tbl.AcceptChanges()

End If

The ImportTable method looks like this:

Public Sub ImportTable(ByVal conn As String, ByVal tbl As DataTable)

'tbl is destination table to update, conn is the source connection string

Table_Label.Text = tbl.TableName

Using connection As New OleDbConnection(conn)

connection.Open()

tbl.Clear()

ProgressBar1.Value = 0

Select Case tbl.TableName

Case "ClientInfo"

'

'handle New Clientinfo table changes

Import_ClientInfo(tbl, connection)

. . .

Case Else

'

'do generic (unchanged table) import

Import_Generic(tbl, connection)

End Select

End Using

End Sub

In the actual import method I use a reader to get the legacy data (in rows). I clear the destination table and add new rows to it (changing some data fields in the iteration. The following is an example:

Private Sub Import_ClientInfo(ByVal tbl As DataTable, ByVal conn As OleDbConnection)

Dim t As ClientInfoDataTable = CType(tbl, ClientInfoDataTable)

'count rows and setup progress bar, also use it to verify rows

SetmaxRows("ClientInfo", conn)

Dim reader As OleDbDataReader = GetReader(conn, "SELECT * FROM ClientInfo")

If reader IsNot Nothing Then

Dim index As Integer() = GetOrdinals(t, reader)

'these columns have been changed

'birthday was stored in 3 columns (d, m, y); is now one date column

Dim di As Integer = reader.GetOrdinal("ClientBirthdayDay")

Dim mi As Integer = reader.GetOrdinal("ClientBirthdayMonth")

Dim yi As Integer = reader.GetOrdinal("ClientBirthdayYear")

Dim bd As Integer = t.ClientBirthdayColumn.Ordinal

'these column names have changed

Dim si As Integer = reader.GetOrdinal("ClientSex")

Dim gi As Integer = t.ClientGenderColumn.Ordinal

index(gi) = si

'these are new columns

Dim pi As Integer = t.IsPersonColumn.Ordinal

If reader.HasRows Then

While reader.Read()

'

' Create a new DataRow.

Dim row As ClientInfoRow

row = CType(t.NewRow(), ClientInfoRow)

'set all new fields "IsPerson = True" row(pi) = True

'

'convert the day, month, year values to a date

row(bd) = Convert_Date(reader, di, mi, yi)

'

'fill the other matching columns

FillMatchingColumns(t, reader, index, row)

t.Rows.Add(row)

End While

End If

reader.Close()

End If

End Sub

On completion of this table control returns to the Import method which does a

tbl.AcceptChanges()

and on when the user is done the ‘OK_Button�method of the dialog does a

Me.TableAdapterManager1.UpdateAll(DataSet1)

before closing.

Next time I run the application the imported changes are not there. What am I doing wrong? Obviously I have omitted code above to simplify the examples, but the concept is shown. Can someone please help me?


Ryn
Ryn
  • Moved byeryangMSFTTuesday, November 24, 2009 2:15 AMwrong forum (From:.NET Base Class Library)
  •  
Ryn  Monday, November 23, 2009 2:08 PM

Not sure, but looks like your tbl.AcceptChanges call should be within the for loop.

For Each nd As TreeNode In TreeView1.Nodes

            If nd.Checked Then

                Dim tbl As DataTable = DataSet1.Tables(nd.Text)

                ImportTable(fromConnection, tbl)
				
				If tbl.HasErrors Then

                          ‘handle errors 
                Else
                      �If no errors, AcceptChanges.

                           tbl.AcceptChanges()
                End If

Next


If that doesnt help, are there any errors/exceptions that you are seeing ?
AnanthR  Monday, November 23, 2009 6:56 PM
Thank you for the reply. You are right about the loop, but unfortunately that is an error in the snippet I pasted. The real code has the "next" where you show it.

Thereare no errors when I run this code. Also, the section between "for each ..."and "next" is in a "Try/Catch" block (with no errors caught).

After the import I can display the table by binding it to a DataGridview and display the contents. Everything is correct. So the poblem must be that the memory cache is updated correctly, but not written back to the database. Also, when I return to the form that called this ImportDialog, the caller still has the old data when referencing the dataset. Must I re-fill the data? I assumed the dataset is shared between all modules.

I am not very familiar with datacentric applications, and ADO is new to me. At this stage I dont know ifI am looking for a coding error or a conceptual error. Is the concept of what I am trying correct?

Any comments on my problem will be appreciated, even just if I am on the right or wrong path.
Ryn
Ryn  Tuesday, November 24, 2009 7:45 AM
"The importer correctly imports the data and writes new tables, but each time I restart the application I have the old data back. "

There must be something wrong with your Form_Load when your application restart. Take a look at your code again especially in Form_Load.
Harrie KalaChakra  Tuesday, November 24, 2009 8:10 AM

Thank you. I looked at the load event. That seems OK, but I eventually found that the SQL Fill string for the table is wrong when I look at it from the data designer panel.

The columns I added are not in the SQL string, but they are shown in the table. When I look at the fill query with the SQL designer I notice that the columns I deleted are still in the list, but not ticked. The columns I added are not in the list. It seems as if my changes to the table have not been applied to the dataset.

But how should I do that?


Ryn
Ryn  Tuesday, November 24, 2009 12:19 PM
"It seems as if my changes to the table have not been applied to the dataset. "



So, take a look at these sites:

http://www.astahost.com/info.php/vbnet-ms-access-interaction-tutorial-part_t12054.html

http://www.startvbdotnet.com/ado/msaccess.aspx

Learn how to create new table, fetch/retrieve data, and record data to Ms Access. Hope U'll like it ;)



-Harrie-
Harrie KalaChakra  Wednesday, November 25, 2009 2:38 AM
Harrie,
Thanks that was usefull (I wish I had those tutorial 3 weeks ago:-)), but my problem is to save changes made to the tables in the designer -- at design time, not run time.
Ryn
Ryn  Wednesday, November 25, 2009 8:00 AM

Thank you All for your friendly help!

Hi Ryn,

Welcometo MSDN forums!

Question: Why does the database seem not get updated after restarting my application?


CAUSE:
When you add a database file to your project via the Add Data Source Wizard, Visual Studio .NET actually maintains two copies of the database, one in the Project folder, andthe otherin the bin folder. Each time when the application is restarted, the former is copied to the latter, so you get a clean copy.

SOLUTION:
Highlight the database in
Solution Explorer -> right click on your database (.mdf) file -> select Properties ->change the "copy to ouput directory" property value to "copy if newer".

This blog is beneficial to you.
https://blogs.msdn.com/smartclientdata/archive/2005/08/26/456886.aspx


Similar issue for you to check:
http://social.msdn.microsoft.com/forums/en-US/vbgeneral/thread/f06363ee-0949-4204-b927-9684d1cfec6e


Best regards,
Martin Xie


Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
Martin Xie - MSFT  Monday, November 30, 2009 6:10 AM

Additionally, here are four methods tomake simple Data Access application(

Next, Previous, First, Last, Update,Delete,Insert, Save) for you to check.

Method 1:Update (Insert/Update/Delete) data back into MS Access database from DataGridView.
http://social.msdn.microsoft.com/forums/en-US/Vsexpressvb/thread/5980181e-f666-4f0a-ab50-c4ebecf96f02/

ImportsSystem.Data.OleDb

PublicClassForm1

DimmyDAAsOleDbDataAdapter

DimmyDataSetAsDataSet

PrivateSubForm1_Load(ByValsenderAsSystem.Object,ByValeAsSystem.EventArgs)HandlesMyBase.Load

DimconAsOleDbConnection=NewOleDbConnection("Provider=Microsoft.jet.oledb.4.0;datasource=|DataDirectory|\myDB.mdb")

DimcmdAsOleDbCommand=NewOleDbCommand("SELECT*FROMTable1",con)

con.Open()

myDA=NewOleDbDataAdapter(cmd)

'AutomaticallygeneratesDeleteCommand,UpdateCommandandInsertCommandforDataAdapterobject

DimbuilderAsOleDbCommandBuilder=NewOleDbCommandBuilder(myDA)

myDataSet=NewDataSet()

myDA.Fill(myDataSet,"MyTable")

DataGridView1.DataSource=myDataSet.Tables("MyTable").DefaultView

con.Close()

con=Nothing

EndSub

'Savedatabackintodatabase

PrivateSubButton1_Click(ByValsenderAsSystem.Object,ByValeAsSystem.EventArgs)HandlesButton1.Click

Me.Validate()

Me.myDA.Update(Me.myDataSet.Tables("MyTable"))

Me.myDataSet.AcceptChanges()

EndSub

EndClass



Method 2: Execute Select/Insert/Delete/Update T-SQL commands in VB.NET code
Code sample: How to Select/Insert/Delete/Update records in MS Access database in VB.NET
http://forums.msdn.microsoft.com/en-US/vbgeneral/thread/87913f28-992d-4705-963b-cb0ffa53d8dd/
Code sample: How to Select/Insert/Delete/Update records in SQL Server database in VB.NET
http://forums.msdn.microsoft.com/en-US/vbgeneral/thread/89e1067d-16e7-44e8-b12d-d78845bf255f/


Method 3
.
Using Data Wizard with BindingNavigator control.
Please check the 11th post in this threadfor detailed walkthrough
:
http://social.msdn.microsoft.com/forums/en-US/Vsexpressvb/thread/ff3f953b-da66-4f03-b4e4-981bab7d783b/




Method 4. Using DataSet/DataTable/DataAdapter in VB.NET code
Please check the 12th post and 13th post in this thread for detailed code sample:
http://social.msdn.microsoft.com/forums/en-US/Vsexpressvb/thread/ff3f953b-da66-4f03-b4e4-981bab7d783b/



Best regards,
Martin Xie
Martin Xie - MSFT  Monday, November 30, 2009 6:12 AM

Hi. Martin,

Thanks for the reply, but the issue is not yet resolved. I have now got more information. It seems that the fill method for some of the tables is incorrect.

This is what I did and where I am now.

  1. I added an Access database using the Data Source Configuration wizard in VS 2008.
  2. I ticked the tables I wanted and created a dataset.
  3. I then edited some tables (removed, inserted or chanted some columns) using the dataset designer.

What I have now established is that:

    • The fill command is not updated and does not reflect the new columns
    • The Query Builder shows the old (removed) columns, although un-ticked
    • The new columns are not shown in the query builder.

So clearly then the Dataset Designer has configured the dataset, but not the source database and is still looking at the original (legacy) database.

I wanted to do is create a brand new database. To save time I want to copy the legacy database structure (there are some 30 -40 tables, some of them have some 70 or so columns). I am trying to do this at design time, not at run time.

I have written an importer that will import the data from an old database and this works. But I don’t know how to create the new database in VS 2008/2010.

I have read everything I can find and can tell you all about using the Northwind or AdventureWorks databse, but I cant figure how to make a new database from that!

Regards


Ryn
Ryn  Monday, November 30, 2009 1:49 PM
"...I then edited some tables (removed, inserted or chanted some columns) using the dataset designer."

Ryn,

I think this is going to be the source of your problems. I believe that if you modify an existing DataSet object which you created thru the designer/wizard, then you really need to re-build it from scratch. I have no idea the issues that get invoked, I tend to stay away from those designer/wizard thingies as much as possible and simply code ALL of my DataAccess stuff.

Anyway, I recently have been working wtih Crystal Reports and requires a DataSet be built, which I did, but when I made any changes to that DataSet it would produce incorrect results. After removing and then completely re-building the ds with the changes I wanted, only then did it seem to work.

Hope this helps, I know it may not be exactly the best solution and or explanation, but my limited experience with those designers limits me a bit. Again, I ususally will just produce my own DataAccess code.

jfc
jamesfreddyc  Monday, November 30, 2009 3:05 PM
jfc,
Thanks. I think you are partly right. I am changing the DataSet, not the dataBase. But the existing database has so many tables and colums that I need to code, I was hoping to find a better way. Surely there must be a way that one can create a new database in a designer?
Ryn
Ryn  Monday, November 30, 2009 3:40 PM
Ryn,

re: "...But the existing database has so many tables and colums that I need to code, I was hoping to find a better way"

Again, this is coming from someone who intentionally stays away from the designers, so take whatever out of it that might help. I'm probably not the best source here, but I'd suggest you revisit and spend more time correctly developing the database. There shouldn't be abigneed to re-work the db side of things once you begin app dev, only minor architecture tweaks may be needed along the way, but the bulk of thework to get the db right should be complete before app dev, IMO. Looking for ways to modify and or createthe db thru data desingers in Visual Studio just doesn't sound like something I'd consider.

My approach to application dev is database-centric. That is, get the db architecture done right is the first step before any VB code is written. Next would be developing most of my business entities, followed with UI components for the presentation layer. You see, I tend to view the app as a way to model the data itself, and of course implement behavior on that data -- that is to 'do stuff' to and with the data.

I'd recommend revisiting the db again. Get it right now, then approach your app dev.

jfc
jamesfreddyc  Monday, November 30, 2009 4:28 PM
"... how to create the new database in VS 2008/2010 "


http://msdn.microsoft.com/en-us/library/z6sa01t4.aspx
Harrie KalaChakra  21 hours 42 minutes ago

<<Note: 
Applies only to Microsoft SQL Server databases>>
I tried this, but how do I then get the existing legacy table structure into the new empty database as a starting point to edit. I can't see any form of import, or how to specify a schema.


Ryn
Ryn  21 hours 27 minutes ago

You can use google to search for other answers

Custom Search

More Threads

• 2D array for 81198 records, it working slow!
• Trapping Keys from a WebBrowser control
• how to load applications in tabcontrol..
• earning my medals 2
• Fingerprint readers
• dBase III memo files when using VB-2005
• Random number generater questions
• Can't hide my main form no matter what I do ... yes, newby alert!!!!!
• want to change color in SFTTree version 6.5
• Using text from a textBox