C# 如何构建 OleDbCommand 查询,以便我可以从一个 .MDB 中获取表,并在另一个 .MDB 中替换它们

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/520506/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 06:34:58  来源:igfitidea点击:

How do I structure an OleDbCommand Query so that I can take Tables from one .MDB, and replace them in another .MDB

c#sqldatatabledatasetoledbcommand

提问by OneShot

I am trying to take tables from one Access Database File, add them to another Access Database file with the exact same structure but with different information. I need to overwrite any existing tables. I am almost done with my project this is last my brick wall.

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

I am using a separate class file named DatabaseHandling.cs to work with the Access Database files.

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

Here is my ENTIRE current DatabaseHandling.cs code. This is kept up to date for now on.

这是我当前的整个 DatabaseHandling.cs 代码。这是目前保持最新状态。

Code:

代码:

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);
                }
            }
        }



        }          
    }

I simply want to take a Datatable that is in memory and write it to a .MDB file. I have been attempting to do this for over 30 hours.

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

LATEST EDIT:

最新编辑:

Okay, added new code. I get a new run-time error: Syntax error in FROM clause.

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

Code:

代码:

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. !!!
        }
    }
}

Once again, it does not work. Let me know if you need additional information.

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

采纳答案by bendewey

Try replacing

尝试更换

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

with

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` = ?)");

Where the queries are valid to your table structure.

查询对您的表结构有效的地方。

回答by Mark Brackett

I get the feeling you're not really grokking the whole DataTable/DataRow thing. You see, in a database, you don't really work with tables- but with rows. If you want to "overwrite" TableB with TableA's rows, you'd first delete all of the rows in TableB and then insert copies of all the rows from TableA.

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

Assuming the destination table already exists, you can do the insert by filling from 1 source, and then setting the rows to Added. The DataAdapter will then run a SQL insert command for each added row.

假设目标表已经存在,您可以通过从 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);
        }
    }    
}

EDIT: Split the OverwriteTable to a different method to accomodate your in memory data table. Also added quotes around generated Sql statements for your reserved Year and Month column names. Moved dispose of CommandBuilder as fixedby bendewey.

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

回答by bendewey

@Mark Brackett had it really close the reason your getting the no DeleteCommand is because the OleDbCommandBuilder is disposing so move that bracket and you should be good.

@Mark Brackett 真的很接近你得到 no 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);
    }
}

Update

更新

Try this exception code

试试这个异常代码

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);
    }
}

update

更新

try changing

尝试改变

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

to

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

I'm tempted to know if its just one row that;s throwing the bug or if its the query. My thought is that one of the rows has a funky value

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