【问题标题】:How do I structure an OleDbCommand Query so that I can take Tables from one .MDB, and replace them in another .MDB如何构建 OleDbCommand 查询,以便我可以从一个 .MDB 中获取表,并在另一个 .MDB 中替换它们
【发布时间】:2010-10-05 22:49:48
【问题描述】:

我正在尝试从一个 Access 数据库文件中获取表,将它们添加到另一个具有完全相同结构但具有不同信息的 Access 数据库文件中。我需要覆盖任何现有的表。我的项目快完成了,这是我的最后一堵砖墙。

我正在使用一个名为 DatabaseHandling.cs 的单独类文件来处理 Access 数据库文件。

这是我当前的全部 DatabaseHandling.cs 代码。暂时保持最新状态。

代码:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.IO;
using System.Linq;
using System.Text;

namespace LCR_ShepherdStaffupdater_1._0
{
    public class DatabaseHandling
    {
        static DataTable datatableB = new DataTable();
        static DataTable datatableA = new DataTable();
        public static DataSet datasetA = new DataSet();
        public static DataSet datasetB = new DataSet();
        static OleDbDataAdapter adapterA = new OleDbDataAdapter();
        static OleDbDataAdapter adapterB = new OleDbDataAdapter();
        static string connectionstringA = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + Settings.getfilelocationA();
        static string connectionstringB = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + Settings.getfilelocationB();
        static OleDbConnection dataconnectionB = new OleDbConnection(connectionstringB);
        static OleDbConnection dataconnectionA = new OleDbConnection(connectionstringA);
        static DataTable tableListA;
        static DataTable tableListB;

        static public void addTableA(string table, bool addtoDataSet)
        {
            dataconnectionA.Open();
            datatableA = new DataTable(table);
            try
            {
                OleDbCommand commandselectA = new OleDbCommand("SELECT * FROM [" + table + "]", dataconnectionA);
                adapterA.SelectCommand = commandselectA;
                adapterA.Fill(datatableA);
            }
            catch
            {
                Logging.updateLog("Error: Tried to get " + table + " from DataSetA. Table doesn't exist!", true, false, false);
            }

            if (addtoDataSet == true)
            {
                datasetA.Tables.Add(datatableA);
                Logging.updateLog("Added DataTableA: " + datatableA.TableName.ToString() + " Successfully!", false, false, false);
            }

            dataconnectionA.Close();
        }

        static public void addTableB(string table, bool addtoDataSet)
        {
            dataconnectionB.Open();
            datatableB = new DataTable(table);

            try
            {
                OleDbCommand commandselectB = new OleDbCommand("SELECT * FROM [" + table + "]", dataconnectionB);
                adapterB.SelectCommand = commandselectB;
                adapterB.Fill(datatableB);
            }
            catch
            {
                Logging.updateLog("Error: Tried to get " + table + " from DataSetB. Table doesn't exist!", true, false, false);
            }



            if (addtoDataSet == true)
            {
                datasetB.Tables.Add(datatableB);
                Logging.updateLog("Added DataTableB: " + datatableB.TableName.ToString() + " Successfully!", false, false, false);
            }

            dataconnectionB.Close();
        }

        static public string[] getTablesA(string connectionString)
        {
            dataconnectionA.Open();
            tableListA = dataconnectionA.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new Object[] { null, null, null, "TABLE" });
            string[] stringTableListA = new string[tableListA.Rows.Count];

            for (int i = 0; i < tableListA.Rows.Count; i++)
            {
                stringTableListA[i] = tableListA.Rows[i].ItemArray[2].ToString();
            }
            dataconnectionA.Close();
            return stringTableListA;
        }

        static public string[] getTablesB(string connectionString)
        {
            dataconnectionB.Open();
            tableListB = dataconnectionB.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new Object[] { null, null, null, "TABLE" });
            string[] stringTableListB = new string[tableListB.Rows.Count];

            for (int i = 0; i < tableListB.Rows.Count; i++)
            {
                stringTableListB[i] = tableListB.Rows[i].ItemArray[2].ToString();
            }
            dataconnectionB.Close();
            return stringTableListB;
        }

        static public void createDataSet()
        {

            string[] tempA = getTablesA(connectionstringA);
            string[] tempB = getTablesB(connectionstringB);
            int percentage = 0;
            int maximum = (tempA.Length + tempB.Length);

            Logging.updateNotice("Loading Tables...");
            Logging.updateLog("Started Loading File A", false, true, false);
            for (int i = 0; i < tempA.Length ; i++)
            {
                if (!datasetA.Tables.Contains(tempA[i]))
                {
                    addTableA(tempA[i], true);
                    percentage++;
                    Logging.loadStatus(percentage, maximum);
                }
                else
                {
                    datasetA.Tables.Remove(tempA[i]);
                    addTableA(tempA[i], true);
                    percentage++;
                    Logging.loadStatus(percentage, maximum);
                }
            }
            Logging.updateLog("Finished loading File A", false, true, false);
            Logging.updateLog("Started loading File B", false, true, false);
            for (int i = 0; i < tempB.Length ; i++)
            {
                if (!datasetB.Tables.Contains(tempB[i]))
                {
                    addTableB(tempB[i], true);
                    percentage++;
                    Logging.loadStatus(percentage, maximum);
                }
                else
                {
                    datasetB.Tables.Remove(tempB[i]);
                    addTableB(tempB[i], true);
                    percentage++;
                    Logging.loadStatus(percentage, maximum);
                }
            }
            Logging.updateLog("Finished loading File B", false, true, false);


        }

        static public DataTable getDataTableA()
        {
            datatableA = datasetA.Tables[Settings.textA];

            return datatableA;
        }
        static public DataTable getDataTableB()
        {
            datatableB = datasetB.Tables[Settings.textB];
            return datatableB;
        }

        static public DataSet getDataSetA()
        {
            return datasetA;
        }

        static public DataSet getDataSetB()
        {
            return datasetB;
        }

        static public void InitiateCopyProcessA()
        {
            DataSet tablesA;
            tablesA = DatabaseHandling.getDataSetA();

                foreach (DataTable table in tablesA.Tables)
                {
                    OverwriteTable(table, table.TableName);
                    Logging.updateLog("Copied " + table.TableName + " successfully.", false, true, false);
                }

        }

        static void OverwriteTable(DataTable sourceTable, string tableName)
        {
            using (var destConn = new OleDbConnection(connectionstringA))
            using (var destCmd = new OleDbCommand(tableName, destConn) { CommandType = CommandType.TableDirect })
            using (var destDA = new OleDbDataAdapter(destCmd))
            {
                // Since we're using a single table, we can have the CommandBuilder
                // generate the appropriate INSERT and DELETE SQL statements
                using (var destCmdB = new OleDbCommandBuilder(destDA))
                {
                    destCmdB.QuotePrefix = "["; // quote reserved column names
                    destCmdB.QuotePrefix = "]";
                    destDA.DeleteCommand = destCmdB.GetDeleteCommand();
                    destDA.InsertCommand = destCmdB.GetInsertCommand();

                    // Get rows from destination, and delete them
                    var destTable = new DataTable();
                    destDA.Fill(destTable);
                    foreach (DataRow dr in destTable.Rows)
                    {
                        dr.Delete();
                    }
                    destDA.Update(destTable);

                    // Set rows from source as Added, so the DataAdapter will insert them
                    foreach (DataRow dr in sourceTable.Rows)
                    {
                        dr.SetAdded();
                    }
                    destDA.Update(sourceTable);
                }
            }
        }



        }          
    }

我只想获取内存中的数据表并将其写入 .MDB 文件。我已经尝试这样做了 30 多个小时。

最新编辑:

好的,添加了新代码。我收到一个新的运行时错误:FROM 子句中的语法错误。

代码:

static public void InitiateCopyProcessA()
{
    DataSet tablesA;
    tablesA = DatabaseHandling.getDataSetA();

        foreach (DataTable table in tablesA.Tables)
        {
            OverwriteTable(table, table.TableName);
            Logging.updateLog("Copied " + table.TableName + " successfully.", false, true, false);
        }

}

static void OverwriteTable(DataTable sourceTable, string tableName)
{
    using (var destConn = new OleDbConnection(connectionstringA))
    using (var destCmd = new OleDbCommand(tableName, destConn) { CommandType = CommandType.TableDirect })
    using (var destDA = new OleDbDataAdapter(destCmd))
    {
        // Since we're using a single table, we can have the CommandBuilder
        // generate the appropriate INSERT and DELETE SQL statements
        using (var destCmdB = new OleDbCommandBuilder(destDA))
        {
            destCmdB.QuotePrefix = "["; // quote reserved column names
            destCmdB.QuotePrefix = "]";
            destDA.DeleteCommand = destCmdB.GetDeleteCommand();
            destDA.InsertCommand = destCmdB.GetInsertCommand();

            // Get rows from destination, and delete them
            var destTable = new DataTable();
            destDA.Fill(destTable);
            foreach (DataRow dr in destTable.Rows)
            {
                dr.Delete();
            }
            destDA.Update(destTable);

            // Set rows from source as Added, so the DataAdapter will insert them
            foreach (DataRow dr in sourceTable.Rows)
            {
                dr.SetAdded();
            }
            destDA.Update(sourceTable); // !!! Run-time error: Syntax error in FROM clause. !!!
        }
    }
}

再一次,它不起作用。如果您需要更多信息,请告诉我。

【问题讨论】:

  • 您的列名可能已保留。检查我的更新以在列名周围添加引号。并且请...我们可以清理帖子以使其不那么成为线程,而是更多当前的问题吗?我在关注这个时遇到了麻烦......
  • 对不起兄弟,我没有意识到它正在堆积。我会保持最新状态。我深表歉意...
  • 我认为异常是在 destDA.Update(destTable) 行上抛出的——对吗?你能检查一下 destDA.DeleteCommand.CommandText 的值是多少吗?我不太了解 Access SQL,但 MSDN 告诉我它非常符合 ANSI。你用的是什么版本?

标签: c# sql datatable dataset oledbcommand


【解决方案1】:

尝试替换

using (var destCmdB = new OleDbCommandBuilder(destDA)) 
{            
    destDA.DeleteCommand = destCmdB.GetDeleteCommand();            
    destDA.InsertCommand = destCmdB.GetInsertCommand();        
}

destDA.InsertCommand = new OleDbCommand("INSERT INTO `AdminUsers` (`UserName`, `Password`) VALUES (?, ?)");
destDA.DeleteCommand = new OleDbCommand("DELETE FROM `AdminUsers` WHERE (`ID` = ?)");
destDA.UpdateCommand = new OldDbCommand("UPDATE `AdminUsers` SET `UserName` = ?, `Password` = ? WHERE (`ID` = ?)");

查询对您的表结构有效的位置。

【讨论】:

    【解决方案2】:

    @Mark Brackett 真的很接近你没有 DeleteCommand 的原因是因为 OleDbCommandBuilder 正在处理,所以移动那个括号,你应该很好。

    static void CopyTable(string sourceConnectionString, string destinationConnectionString, string tableName)
    {
    // Get rows from source    
    var sourceTable = new DataTable();
    using (var sourceConn = new OleDbConnection(sourceConnectionString))
    using (var sourceCmd = new OleDbCommand(tableName, sourceConn) {CommandType = CommandType.TableDirect})
    using (var sourceDA = new OleDbDataAdapter(sourceCmd))
    {
        sourceDA.Fill(sourceTable);
    }
    using (var destConn = new OleDbConnection(destinationConnectionString))
    using (var destCmd = new OleDbCommand(tableName, destConn) {CommandType = CommandType.TableDirect})
    using (var destDA = new OleDbDataAdapter(destCmd))
    {
        // Since we're using a single table, we can have the CommandBuilder        
        // generate the appropriate INSERT and DELETE SQL statements        
        using (var destCmdB = new OleDbCommandBuilder(destDA))
        {
            destDA.DeleteCommand = destCmdB.GetDeleteCommand();
            destDA.InsertCommand = destCmdB.GetInsertCommand();
    
            // Get rows from destination, and delete them        
            var destTable = new DataTable();
            destDA.Fill(destTable);
            foreach (DataRow dr in destTable.Rows)
            {
                dr.Delete();
            }
            destDA.Update(destTable);
            // Set rows from source as Added, so the DataAdapter will insert them        
            foreach (DataRow dr in sourceTable.Rows)
            {
                dr.SetAdded();
            }
            destDA.Update(sourceTable);
        }
    }
    

    更新

    试试这个异常代码

    static public void InitiateCopyProcessA()
    {
        DataSet tablesA;
        tablesA = DatabaseHandling.getDataSetA();
        int i = 0;
        string tableName = "";
        try
        {
            foreach (DataTable table in tablesA.Tables)
            {
                tableName = table.TableName;  // for debugging the exception
                CopyTable(connectionstringA, connectionstringB, table.TableName);
            }
        }
        catch(Exception ex)
        {
            throw new Exception("Error updating " + tableName, ex);
        }
    }
    

    更新

    尝试改变

    // Set rows from source as Added, so the DataAdapter will insert them                
    foreach (DataRow dr in sourceTable.Rows)        
    {            
        dr.SetAdded();        
    }
    

    // only add the first row.
    sourceTable.Rows[0].SetAdded()
    

    我很想知道它是否只是引发错误的一行,或者它是否是查询。我的想法是其中一行有一个时髦的值

    【讨论】:

    • 试过了,几乎成功了,然后我得到一个运行时错误:INSERT INTO 语句中的语法错误。
    • 您要测试多少行?尝试仅测试 1 行。还要设置一个断点并将鼠标悬停在 destDA.InsertCommand 上,看看它的 CommandText 是什么。在您的问题中发布。
    • 好吧,我照你说的做了。我不确定你只测试一行是什么意思,但我想我按照你的要求做了。让我知道你的想法。再次感谢你,我非常感激。
    • 您将不得不在其中放入某种逻辑来确定哪个表对您不利。查看我的更新示例
    • 好主意。我的表是“更新 AccountBudget 时出错” AccountBudget 到底有什么问题???
    【解决方案3】:

    我感觉您并没有真正了解整个 DataTable/DataRow 的东西。您会看到,在数据库中,您并没有真正使用 tables,而是使用行。如果您想用 TableA 的行“覆盖”TableB,您首先要删除 TableB 中的所有行,然后插入 TableA 中所有行的副本。

    假设目标表已经存在,您可以通过从 1 个源填充来进行插入,然后将行设置为已添加。然后,DataAdapter 将为每个添加的行运行 SQL 插入命令。

    static void CopyTable(string sourceConnectionString, string destinationConnectionString, string tableName) {
        // Get rows from source
        var sourceTable = new DataTable();
        using (var sourceConn = new OleDbConnection(sourceConnectionString))
        using (var sourceCmd = new OleDbCommand(tableName, sourceConn) { CommandType = CommandType.TableDirect })
        using (var sourceDA = new OleDbDataAdapter(sourceCmd)) {
            sourceDA.Fill(sourceTable);
        }
    
        OverwriteTable(sourceTable, destinationConnectionString, tableName);
    }
    
    static void OverwriteTable(DataTable sourceTable, string destinationConnectionString, string tableName) {
        using (var destConn = new OleDbConnection(destinationConnectionString))
        using (var destCmd = new OleDbCommand(tableName, destConn) { CommandType = CommandType.TableDirect })
        using (var destDA = new OleDbDataAdapter(destCmd)) {
            // Since we're using a single table, we can have the CommandBuilder
            // generate the appropriate INSERT and DELETE SQL statements
            using (var destCmdB = new OleDbCommandBuilder(destDA)) {
                destCmdB.QuotePrefix = "["; // quote reserved column names
                destCmdB.QuoteSuffix = "]";
                destDA.DeleteCommand = destCmdB.GetDeleteCommand();
                destDA.InsertCommand = destCmdB.GetInsertCommand();
    
                // Get rows from destination, and delete them
                var destTable = new DataTable();
                destDA.Fill(destTable);
                foreach (DataRow dr in destTable.Rows) {
                    dr.Delete();
                }
                destDA.Update(destTable);
    
                // Set rows from source as Added, so the DataAdapter will insert them
                foreach (DataRow dr in sourceTable.Rows) {
                   dr.SetAdded(); 
                }
                destDA.Update(sourceTable);
            }
        }    
    }
    

    编辑:将 OverwriteTable 拆分为不同的方法以适应您的内存数据表。还为您保留的 Year 和 Month 列名称在生成的 Sql 语句周围添加了引号。将 CommandBuilder 的 dispose 移动为 fixed bendewey

    【讨论】:

    • 感谢您的回复。我不知道我必须逐行进行。我复制并粘贴了您的代码并运行它以查看它是否有效,但出现运行时错误:“当传递带有已删除行的 DataRow 集合时,更新需要有效的 DeleteCommand。”我做错了什么?
    • 我需要知道如何获取内存中已有的数据表,然后覆盖 Access 数据库文件表。不要直接从 .MDB 文件中获取表并将其直接添加到另一个 .MDB 文件中。你明白我在说什么吗?我该怎么做?
    • 只是不要从源代码中获取...我为您将代码拆分为 2 个方法。
    • 谢谢 - 看看它是否有效。如果是这样,我的上帝,我不知道如何感谢你或其他帮助我的人。快速提问...编译器找不到这个 destDA.QuotePrefix 或 destDA.QuoteSuffix。你确定这就是你的意思,因为这不起作用吗?
    • 不...我打错了(并且没有测试)。它应该是 destCmdB.Quote*。固定。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-25
    相关资源
    最近更新 更多