Update linked tables in MS Access Database with C#

2020-07-18 05:26发布

I have two Access 2003 databases (fooDb and barDb). There are four tables in fooDb that are linked to tables in barDb.

Two questions:

  • How do I update the table contents (linked tables in fooDb should be synchronized with the table contents in barDb)
  • How do I re-link the table to a different barDb using ADO.NET

I googled but didn't get any helpful results. What I found out is how to accomplish this in VB(6) and DAO, but I need a solution for C#.

2条回答
▲ chillily
2楼-- · 2020-07-18 05:43

Here is my solution to relinking DAO tables using C#.

My application uses a central MS Access database and 8 actual databases that are linked in. The central database is stored locally to my C# app but the application allows for the 8 data databases to be located elsewhere. On startup, my C# app relinks DAO tables in the central database based on app.config settings.

Aside note, this database structure is the result of my app originally being a MS Access App which I ported to VB6. I am currently converting my app to C#. I could have moved off MS Access in VB6 or C# but it is a very easy to use desktop DB solution.

In the central database, I created a table called linkedtables with three columns TableName, LinkedTableName and DatabaseName.

On App start, I call this routine

            Common.RelinkDAOTables(Properties.Settings.Default.DRC_Data
                              , Properties.Settings.Default.DRC_LinkedTables
                              , "SELECT * FROM LinkedTables");

Default.DRC_Data - Current folder of central access DB Default.DRC_LinkedTables - Current folder of 8 data databases

Here is code does the actual relinking of the DAO Tables in C#

        public static void RelinkDAOTables(string MDBfile, string filepath, string sql)
    {
        DataTable linkedTables = TableFromMDB(MDBfile, sql);

        dao.DBEngine DBE = new dao.DBEngine();
        dao.Database DB = DBE.OpenDatabase(MDBfile, false, false, "");
        foreach (DataRow row in linkedTables.Rows)
        {
            dao.TableDef table = DB.TableDefs[row["Name"].ToString()];
            table.Connect = string.Format(";DATABASE={0}{1} ;TABLE={2}", filepath, row["database"], row["LinkedName"]);
            table.RefreshLink();
        }


    }

Additional code written to fetch data from a access database and return it as a DataTable

        public static DataTable TableFromOleDB(string Connectstring, string Sql)
    {
        try
        {
            OleDbConnection conn = new OleDbConnection(Connectstring);
            conn.Open();
            OleDbCommand cmd = new OleDbCommand(Sql, conn);
            OleDbDataAdapter adapter = new OleDbDataAdapter(cmd);
            DataTable table = new DataTable();
            adapter.Fill(table);

            return table;
        }
        catch (OleDbException)
        {
            return null;
        }
    }
    public static DataTable TableFromMDB(string MDBfile, string Sql)
    {
        return TableFromOleDB(string.Format(sConnectionString, MDBfile), Sql);
    }
查看更多
男人必须洒脱
3楼-- · 2020-07-18 06:01

If you're coding in C#, then Access is not involved, only Jet. So, you can use whatever method you want to access the data and then code the updates.

I've coded this kind of thing in Access many times, and my approach for each table is:

  1. run a query that deletes from fooDB that no longer exist in barDB.

  2. run a query that inserts into fooDB records that are in barDB that do not yet exist in fooDB.

  3. I always use code that writes on-the-fly SQL to update the fooDB table with the data from barDB.

The 3rd one is the hard one. I loop through the fields collection in DBA and write SQL on the fly that would be something like this:

UPDATE table2 INNER JOIN table1 ON table2.ID = table1.ID
SET table2.field1=table1.field1
WHERE (table2.field1 & "") <> (table1.field1 & "")

For numeric fields you'd have to use your available SQL dialect's function for converting Null to zero. Running Jet SQL, I'd use Nz(), of course, but that doesn't work via ODBC. Not sure if it will work with OLEDB, though.

In any event, the point is to issue a bunch of column-by-column SQL updates instead of trying to do it row by row, which will be much less efficient.

查看更多
登录 后发表回答