Как структурировать запрос OleDbCommand, чтобы я мог брать таблицы из одного .MDB и заменять их в другом .MDB

Я пытаюсь взять таблицы из одного файла базы данных 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);
                }
            }
        }



        }          
    }

Я просто хочу взять Datatable, который находится в памяти, и записать его в файл .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. !!!
        }
    }
}

Опять же, не работает. Сообщите мне, если вам понадобится дополнительная информация.


person Community    schedule 06.02.2009    source источник
comment
Имена ваших столбцов, вероятно, зарезервированы. Проверьте мое обновление, чтобы добавить кавычки вокруг имен столбцов. И, пожалуйста ... можем ли мы очистить пост, чтобы сделать его менее тематическим, а в большей степени актуальным вопросом? У меня проблемы с отслеживанием этого ....   -  person Mark Brackett    schedule 07.02.2009
comment
Извини, братан, я не осознавал, что он накапливается. Я буду поддерживать его в актуальном состоянии. Мои глубочайшие извинения ...   -  person OneShot    schedule 07.02.2009
comment
Я предполагаю, что исключение выбрасывается в строку destDA.Update (destTable) - это правильно? Можете ли вы проверить значение destDA.DeleteCommand.CommandText? Я не так хорошо знаю Access SQL, но MSDN говорит мне, что он вполне совместим с ANSI. Какую версию ты используешь?   -  person Mark Brackett    schedule 07.02.2009


Ответы (3)


Попробуйте заменить

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

Где запросы действительны для вашей структуры таблицы.

person bendewey    schedule 06.02.2009

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

to

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

Мне хочется узнать, является ли ошибка только одной строкой, или это запрос. Я думал, что одна из строк имеет забавное значение

person bendewey    schedule 06.02.2009
comment
Пробовал, почти сработало, затем я получаю ошибку времени выполнения: синтаксическая ошибка в инструкции INSERT INTO. - person OneShot; 06.02.2009
comment
Сколько строк вы тестируете? попробуйте протестировать только 1 строку. Также установите точку останова и наведите указатель мыши на destDA.InsertCommand и посмотрите, что это за CommandText. опубликуйте это в своем вопросе. - person bendewey; 06.02.2009
comment
Хорошо, я сделал то, что ты сказал. Я не был уверен в том, что вы имели в виду при тестировании только одной строки, но я думаю, что сделал то, что вы просили. Дайте мне знать, что вы думаете. И еще раз спасибо за это, я очень благодарен. - person OneShot; 06.02.2009
comment
Вам нужно будет внедрить в него какую-то логику, чтобы определить, какой стол на вас облажается. Посмотреть мой обновленный образец - person bendewey; 06.02.2009
comment
Отличная идея. Таблица, в которой меня тронули, была Ошибка обновления AccountBudget. Что, черт возьми, не так с AccountBudget ??? - person OneShot; 06.02.2009
comment
У вас есть идеи, что с этим делать? - person OneShot; 06.02.2009
comment
Что вы говорите о внутреннем исключении? он все еще говорит об ошибке синтаксиса? - person bendewey; 06.02.2009
comment
Эй, извини, пошла поесть. Да, мое внутреннее исключение по-прежнему говорит {Синтаксическая ошибка в инструкции INSERT INTO.} - person OneShot; 06.02.2009
comment
Можете ли вы обновить свой пост с помощью команды insert для таблицы AccountBudget - person bendewey; 06.02.2009
comment
Счастлив! Его обновлено. Я еще раз благодарю вас за это, от всего сердца, лол - person OneShot; 06.02.2009
comment
Я сравниваю каждый оператор INSERT INTO. Они делают то же самое. Прослушивание имен и значений количества столбцов значений. Учетная запись успешно скопирована, но затем, когда она попадает в AccountBudget, выдает ошибку. ПОЛНОСТЬЮ озадачивает. - person OneShot; 06.02.2009
comment
Я исследовал это. Я понятия не имею, в чем проблема. Хотите задать новый вопрос именно по этой конкретной проблеме? - person OneShot; 07.02.2009
comment
Этот парень подо мной опубликовал код и сказал, что это исправление. Я собираюсь проверить это. - person OneShot; 07.02.2009
comment
Это не должно быть слишком сложно исправить, верно? Я попробовал этот код ребят ниже, тоже не сработало. - person OneShot; 07.02.2009
comment
Я еще раз думаю, что это как бы отошло от темы. Я подумываю задать вопрос о том, почему я получаю ошибки в моих SQL-запросах. Этот вопрос как бы умер, и я не виню вас, если вы теряете интерес. - person OneShot; 07.02.2009
comment
Я собираюсь начать другой вопрос конкретно по моей новой проблеме - person OneShot; 07.02.2009

У меня такое чувство, что вы на самом деле не разбираетесь в DataTable / DataRow. Видите ли, в базе данных вы на самом деле работаете не с таблицами, а со строками. Если вы хотите «перезаписать» TableB строками TableA, вы должны сначала удалить все строки в 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 на другой метод, чтобы разместить вашу таблицу данных в памяти. Также добавлены кавычки вокруг сгенерированных операторов Sql для зарезервированных имен столбцов года и месяца. Перемещено удаление CommandBuilder как исправлено bendewey.

person Mark Brackett    schedule 06.02.2009
comment
Благодарю за ваш ответ. Я НЕ знал, что мне приходилось делать это строка за строкой. Я скопировал и вставил ваш код и запустил его, чтобы проверить, работает ли он, и у меня возникла ошибка времени выполнения: для обновления требуется действительная команда DeleteCommand при передаче коллекции DataRow с удаленными строками. Что я делаю неправильно? - person OneShot; 06.02.2009
comment
Мне нужно знать, как взять DataTable, который у меня уже есть в памяти, и ЗАТЕМ перезаписать таблицу файлов базы данных Access. Не брать таблицу непосредственно из файла .MDB и добавлять ее непосредственно в другой файл .MDB. Вы понимаете, о чем я говорю? Как мне это сделать? - person OneShot; 06.02.2009
comment
Только не делайте выборку из источника ... Я разделил для вас код на 2 метода. - person Mark Brackett; 07.02.2009
comment
Спасибо - посмотрю, сработает ли это. Если это так, боже мой, я не знаю, как благодарить тебя или того парня, который мне помогает. Быстрый вопрос ... Компилятор не может найти этот destDA.QuotePrefix или destDA.QuoteSuffix. Вы уверены, что это то, что вы имеете в виду, потому что это не работает? - person OneShot; 07.02.2009
comment
Нет ... Я набрал опечатку (и не тестировал). Это должен быть destCmdB.Quote *. Фиксированный. - person Mark Brackett; 07.02.2009
comment
Эй, проверьте мой пост. Я очистил его и добавил к нему новое РЕДАКТИРОВАНИЕ. Я получаю ошибку времени выполнения с вашим кодом - person OneShot; 07.02.2009