C#问题:加载.MDB文件,对其进行更改以及将更改保存回原始文件的最简单方法是什么?

One*_*hot 5 c# datatable oledbconnection dataadapter ms-jet-ace

我正在做的项目差不多完成了.我正在加载.MDB文件,在DataGrid上显示内容并尝试在DataGrid上获取这些更改并将它们保存回.MDB文件.我还将创建一个函数,允许我从一个.MDB文件中获取表并将其保存到另一个.MDB文件中.当然,如果我无法弄清楚如何将更改保存回.MDB文件,我就无法做到这一点.

我对Google进行了广泛的研究,但我的问题没有答案.我认为自己是这个特定主题的初学者所以请不要让答案太复杂 - 我需要最简单的方法来编辑.MDB文件!请提供编程示例.

  1. 假设我已经建立了与DataGrid的连接.如何获取Datagrid所做的更改?我确定这个很简单,可以回答.
  2. 然后,我需要知道如何使用此Datatable,将其插入到数据集中,然后获取该数据集并重写.MDB文件.(如果有一种方法只插入已更改的表,我宁愿这样做.)

提前感谢您,如果您需要更多信息,请与我们联系.这是我可能不得不问这个话题的最后一件事......感谢上帝.

编辑:

我正在使用的.mdb是一个Microsoft Access数据库.(我甚至不知道有多个.mdb文件)

我知道我不能通过编写器或任何东西直接写入.MDB文件,但有没有办法可以生成一个带有DataSet信息的.MDB文件?或者只是一种方法,我可以将表添加到我已经加载到DataGrid的.MDB文件中.有办法!

同样,我需要一种在C#中以编程方式执行此操作的方法.

编辑:

好的,我的项目相当大,但我使用一个单独的类文件来处理所有数据库连接.我知道我的设计和来源非常邋,,但它完成了工作.我和互联网上的例子一样好.

请记住,我只是以另一种形式连接到DataGrid.如果你想要我的代码来自Datagrid表单,请告诉我(我不知道为什么你会需要它).DatabaseHandling.cs处理2个.MDB文件.所以你会看到两个数据集.我最终将使用它来从一个数据集中获取表并将它们放入另一个数据集中.我只需要弄清楚如何将这些值保存到.MDB文件中.

反正有没有这样做?必须有办法...

编辑:

从我研究和阅读的内容......我认为答案就在我的鼻子底下.使用"Update()"命令.现在虽然这是重新确保实际上有一个简单的方法,我仍然留下问题,我没有friggin线索如何使用此更新命令.

也许我可以像这样设置它:

Oledb.OledbConnection cn = new Oledb.OledbConnection(); 
cn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Staff.mdb"; 
Oledb.OledbCommand cmd = new Oledb.OledbCommand(cn); 
cmd.CommandText = "INSERT INTO Customers (FirstName, LastName) VALUES (@FirstName, @LastName)"; 
Run Code Online (Sandbox Code Playgroud)

我认为可能会这样做,但我不想手动插入任何东西.我想要做这两件事:

  • 获取在Datagrid上更改的信息并更新我从中获取的Access数据库文件(.mdb)
  • 创建一个函数,允许我从另一个Access数据库文件(.mdb)中获取表,并将它们替换为辅助Access数据库文件(.mdb).两个文件将使用完全相同的结构,但其中将包含不同的信息.

我希望有人能为此提出答案......我的项目已经完成所有等待的答案就是一个简单的答案.

提前再次感谢您.

编辑:

好的...好消息 我已经想出如何查询.mdb文件本身(我认为).这是代码,它不起作用,因为我试图使用的sql命令导致运行时错误.这将带我到我的下一个问题.

添加到DatabaseHandling.cs的新功能代码:

static public void performSynchronization(string table, string tableTwoLocation)
{
    OleDbCommand cmdCopyTables = new OleDbCommand("INSERT INTO" + table + "SELECT * FROM [MS Access;" + tableTwoLocation + ";].[" + table + "]"); // This query generates runtime error
    cmdCopyTables.Connection = dataconnectionA;
    dataconnectionA.Open();
    cmdCopyTables.ExecuteNonQuery();
    dataconnectionA.Close();
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我实际上设法对连接本身执行查询,我认为这是实际的Access .MDB文件.正如我所说,我在文件上执行的SQL查询不起作用,并在使用时生成运行时错误.

我试图执行的命令应该从.MDB文件中获取一个表,并覆盖相同类型的不同.MDB文件的表.我上面尝试的SQL命令试图直接从.mdb文件中获取一个表,并直接将其放在另一个文件中 - 这不是我想要做的.我想从.MDB文件中获取所有信息 - 将表放入Datatable,然后将所有Datatables添加到数据集(我已经完成了.)我想为两个.MDB文件执行此操作.一旦我有两个数据集,我想从每个数据集中取出特定的表并将它们添加到每个文件中,如下所示:

  • DataSetA >>>> ----- [Add Tables(Overwrite Them)] ----- >>>> DataSetB
  • DataSetB >>>> ----- [Add Tables(Overwrite Them)] ----- >>>> DataSetA

我想把那些数据集拿走,然后将它们放回到它们来自的每个Access .MDB文件中.基本上保持两个数据库同步.

所以我修改的问题是:

  1. 如何创建一个SQL查询,通过覆盖现有的同名名称将表添加到.MDB文件中.应该能够在运行时期间使用一个数组动态创建查询,该数组用我想要添加的表名替换变量.
  2. 如何获取Datagrid对DataTable所做的更改并将它们放回DataTable(或DataSet)中,以便将它们发送到.MDB文件?

我试图尽可能详细说明......因为我相信我并没有很好地解释我的问题.现在这个问题已经变得太长了.我希望我能更好地解释这一点.:[

编辑:

感谢下面的用户,我想我几乎找到了一个修复程序 - 关键字差不多.这是我在下面更新的DatabaseHandling.cs代码.我收到运行时错误"数据类型不匹配".考虑到我试图将这些表复制到具有完全相同设置的另一个数据库中,我不知道这怎么可能.

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

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

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

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



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

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

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


            }

            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)
                {
                    CopyTable(table, connectionstringB);
                }
            }

            public static void CopyTable(DataTable table, string connectionStringB)
            {
                var connectionB = new OleDbConnection(connectionStringB);
                foreach (DataRow row in table.Rows)
                {
                    InsertRow(row, table.Columns, table.TableName, connectionB);
                }
            }

            public static void InsertRow(DataRow row, DataColumnCollection columns, string table, OleDbConnection connection)
            {
                var columnNames = new List<string>();
                var values = new List<string>();

                for (int i = 0; i < columns.Count; i++)
                {
                    columnNames.Add("[" + columns[i].ColumnName + "]");
                    values.Add("'" + row[i].ToString().Replace("'", "''") + "'");
                }

                string sql = string.Format("INSERT INTO {0} ({1}) VALUES ({2})",
                        table,
                        string.Join(", ", columnNames.ToArray()),
                        string.Join(", ", values.ToArray())
                    );

                ExecuteNonQuery(sql, connection);
            }

            public static void ExecuteNonQuery(string sql, OleDbConnection conn)
            {
                if (conn == null)
                    throw new ArgumentNullException("conn");

                ConnectionState prevState = ConnectionState.Closed;
                var command = new OleDbCommand(sql, conn);
                try
                {
                    prevState = conn.State;
                    if (prevState != ConnectionState.Open)
                        conn.Open();

                    command.ExecuteNonQuery(); // !!! Runtime-Error: Data type mismatch in criteria expression. !!!
                }
                finally
                {
                    if (conn.State != ConnectionState.Closed
                        && prevState != ConnectionState.Open)
                        conn.Close();
                }
            }

            }          
        }
Run Code Online (Sandbox Code Playgroud)

为什么我收到此错误?两个表完全相同.我究竟做错了什么?最坏的情况是,在插入具有不同值的完全相同的结构表之前,如何删除其他Access .MDB文件中的表?

男人,我希望我能搞清楚......

编辑:

好的,我已经走了一段距离.我的问题已经变成了一个新问题,因此应该单独提出.我已经回答了我的问题,因为我知道如何直接对我打开的连接执行查询.谢谢你们!

ben*_*wey 3

我不确定您已经走了多远,但如果您正在寻找快速拖放操作,您可能需要考虑创建一个可连接的强类型数据集,并使用数据源工具窗口的拖放功能在视觉工作室中。

那里肯定有样品,但您会想要的。

  1. 创建一个新的数据集
  2. 从服务器资源管理器中的数据连接树中拖放
  3. 创建一个新表单
  4. 从数据源工具中拖动表格
  5. 窗体上的窗口。

更新:

首先,我并不是100%理解你的问题。如果您可以在访问文件之间创建一些 LinkTables(最好),那么您可以使用 SQL 语句(例如“INSERT INTO Customers SELECT FirstName, LastName FROM File2.Customers”)在文件之间复制数据。如果不是这样,我认为您将必须循环数据表并使用类似于上次编辑的 INSERT 语句手动插入记录。至于数据网格,您可能必须通过监视 RowChanged 事件(不确定这是否是确切的事件)来跟踪更改的内容,甚至在行更改时执行插入/更新语句。

更新:

要循环数据表,您可以执行类似的操作。未测试。我刚刚再次更新以包含 MakeValueDbReady 函数。这也没有经过测试,我不确定我是否已经正确处理了所有情况甚至所有情况。您确实必须调试 sql 语句并确保它生成正确的值。每个数据库处理的值都不同。至少通过这种方式,值解析被提取出来。我还意识到,您应该能够从 DataTable 上的属性中获取它,而不是对 TableName 进行硬编码

void CopyTable(DataTable table, string connectionStringB)
{
    var connectionB = new OleDbConnection(connectionStringB);
    foreach(DataRow row in table.Rows)
    {
        InsertRow(row, table.Columns, table.TableName, connectionB);
    }
}

public static void InsertRow(DataRow row, DataColumnCollection columns, string table, OleDbConnection connection)
{
    var columnNames = new List<string>();
    var values = new List<string>();

    // generate the column and value names from the datacolumns    
    for(int i =0;i<columns.Count; i++)
    {
        columnNames.Add("[" + columns[i].ColumnName + "]");
        // datatype mismatch should be fixed by this function
        values.Add(MakeValueDbReady(row[i], columns[i].DataType));
    }

    // create the sql
    string sql = string.Format("INSERT INTO {0} ({1}) VALUES ({2})",
            table,
            string.Join(", ", columnNames.ToArray()),
            string.Join(", ", values.ToArray())
        );

    // debug the accuracy of the sql here and even copy into 
    // a new Query in Access to test
    ExecuteNonQuery(sql, connection);
}

// as the name says we are going to check the datatype and format the value
// in the sql string based on the type that the database is expecting
public string MakeValueDbReady(object value, Type dataType)
{
    if (value == null)
        return null;

    if (dataType == typeof(string))
    {
        return "'" + value.ToString().Replace("'", "''") + "'"
    }
    else if (dataType == typeof(DateTime))
    {
        return "#" + ((DateTime)value).ToString + "#"
    }
    else if (dataType == typeof(bool))
    {
        return ((bool)value) ? "1" : "0";
    }

    return value.ToString();
}

public static void ExecuteNonQuery(string sql, OleDbConnection conn)
{
    if (conn == null)
        throw new ArgumentNullException("conn");

    ConnectionState prevState = ConnectionState.Closed;
    var command = new OleDbCommand(sql, conn);
    try
    {
        // the reason we are checking the prev state is for performance reasons
        // later you might want to open the connection once for the a batch
        // of say 500 rows  or even wrap your connection in a transaction.
        // we don't want to open and close 500 connections
        prevState = conn.State;
        if (prevState != ConnectionState.Open)
            conn.Open();

        command.ExecuteNonQuery();
    }
    finally
    {
        if (conn.State != ConnectionState.Closed
            && prevState != ConnectionState.Open)
            conn.Close();
    }
}
Run Code Online (Sandbox Code Playgroud)