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

发布于 2024-07-14 00:14:19 字数 12865 浏览 4 评论 0原文

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

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

  1. 假设我已经连接到 DataGrid。 如何获取数据网格所做的更改? 我确信这个问题很简单就能回答。
  2. 然后我需要知道如何获取这个数据表,将其插入到它来自的数据集中,然后获取该数据集并重写 .MDB 文件。 (如果有一种方法可以只插入已更改的表,我会更喜欢这种方法。)

提前谢谢您,如果您需要更多信息,请告诉我。 这是我可能要问的关于这个话题的最后一件事……感谢上帝。

编辑:

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

我知道我不能直接写入.mdb文件。通过流写入器或其他方式生成 MDB 文件,但有没有办法可以生成其中已包含数据集信息的 .MDB 文件? 或者是否有一种方法可以将表添加到已加载到 DataGrid 中的 .MDB 文件中。 一定有办法!

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

编辑:

好的,我的项目相当大,但我使用单独的类文件来处理所有数据库连接。 我知道我的设计和来源确实很草率,但它完成了工作。 我只能像我在互联网上找到的例子一样好。

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

有办法做到这一点吗? 必须有一种方法...

编辑:

根据我的研究和阅读...我认为答案就在我眼皮子底下。 使用“Update()”命令。 现在,虽然这再次确保了事实上有一种简单的方法可以做到这一点,但我仍然面临着一个问题,即我不知道如何使用这个更新命令。

也许我可以这样设置:

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

我认为这可以做到,但我不想手动插入任何内容。 我想同时执行这两项操作:

  • 获取 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();
}

正如您所看到的,我实际上已经成功地对连接本身执行了查询,我相信这就是实际的 Access .MDB 文件。 正如我所说,我在该文件上执行的 SQL 查询不起作用,并且在使用时生成了运行时错误。

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

  • DataSetA >>>>>----- [添加表 (覆盖它们)]----->>>> DataSetB
  • DataSetB >>>>>----- [添加表 (覆盖它们)]----->>>> 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();
                }
            }

            }          
        }

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

伙计,我希望我能解决这个问题...

编辑:

好吧,我已经走了一段距离。 我的问题已经变成了一个新问题,因此值得单独提出。 我的问题已经得到解答,因为现在我知道如何直接对我打开的连接执行查询。 谢谢你们!

My project that I am working on is almost finished. I am loading a .MDB file, displaying the contents on a DataGrid and attempting to get those changes on the DataGrid and save them back into the .MDB file. I am also going to create a function that allows me to take the tables from one .MDB file and save it to another .MDB file. Of course, I cannot do any of this if I cannot figure out how to save the changes back to the .MDB file.

I have researched Google extensively and there are no answers to my question. I consider myself a beginner at this specific topic so please don't make the answers too complicated -- I need the simplest way to edit a .MDB file! Please provide programming examples.

  1. Assume that I've already made a connection to a DataGrid. How do I get the changes made by the Datagrid? Im sure this one is simple enough to answer.
  2. I then need to know how to take this Datatable, insert it into Dataset it came from then take that Dataset and rewrite the .MDB file. (If there is a way of only inserting the tables that were changed I would prefer that.)

Thank you in advance, let me know if you need more information. This is the last thing I am probably going to have to ask about this topic...thank god.

EDIT:

The .mdb I am working with is a Microsoft Access Database. ( I didnt even know there were multiple .mdb files)

I know I cannot write directly to the .MDB file via a streamwriter or anything but is there a way I can possibly generated a .MDB File with the DataSet information already in it? OR is there just a way that I can add tables to a .MDB file that i've already loaded into the DataGrid. There HAS to be a way!

Again, I need a way to do this PROGRAMMATICALLY in C#.

EDIT:

Okay, my project is fairly large but I use a seperate class file to handle all Database connections. I know my design and source is really sloppy, but it gets the job done. I am only as good as the examples I find on the internet.

Remember, I am simply connecting to a DataGrid in another form. Let me know if you want my code from the Datagrid form (I dont know why you would need it though). DatabaseHandling.cs handles 2 .MDB files. So you will see two datasets in there. I will use this eventually to take tables from one Dataset and put them into another Dataset. I just need to figure out how to save these values BACK into a .MDB file.

Is there anyway to do this? There has to be a way...

EDIT:

From what i've researched and read...I think the answer is right under my nose. Using the "Update()" command. Now while this is re-assuring that there is infact a simple way of doing this, I am still left with the problem that I have no-friggin-clue how to use this update command.

Perhaps I can set it up like this:

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

I think that may do it, but I dont want to manually insert anything. I want to do both of these instead:

  • Take information that is changed on the Datagrid and update the Access Database File (.mdb) that I got it from
  • Create a function that allows me to take tables from another Access Database File (.mdb) and replace them in a secondary Access Database file (.mdb). Both files will use the exact same structure but will have different information in them.

I hope someone comes up with a answer for this...my project is done all that awaits is one simple answer.

Thank you again in advance.

EDIT:

Okay...good news. I have figured out how to query the .mdb file itself (I think). Here is the code, which doesn't work because I get a runtime error due to the sql command i'm attempting to use. Which will bring me to my next question.

New function code added to 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();
}

As you can see, I've actually managed to execute a query on the connection itself, which I believe to be the actual Access .MDB file. As I said though, the SQL query I've executed on the file doesn't work and generated a run-time error when used.

The command I am attempting to execute is supposed to take a table from a .MDB file and overwrite a table of the same type of a different .MDB file. The SQL command I attempted above tried to directly take a table from a .mdb file, and directly put it in another -- this isn't what I want to do. I want to take all the information from the .MDB file -- put the tables into a Datatable and then add all the Datatables to a Dataset (which i've done.) I want to do this for two .MDB files. Once I have two Datasets I want to take specific tables out of each Dataset and add them to each file like this:

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

I want to take those each those Datasets and then put them BACK into each Access .MDB file they came from. Essentially keeping both databases synchronized.

So my questions, revised, is:

  1. How do I create a SQL query that will add a table to the .MDB file by overwriting the existing one of the same name. The query should be able to be created dynamically during runtime with an array that replaces a variable with the table name I want to add.
  2. How do I get the changes that were made by the Datagrid to the DataTable and put them back into a DataTable (or DataSet) so I can send them to the .MDB file?

I've tried to elaborate as much as possible...because I believe I am not explaing my issue very well. Now this question has grown wayyy too long. I just wish I could explain this better. :[

EDIT:

Thanks to a user below I think I've almost found a fix -- the keyword almost.
Here is my updated DatabaseHandling.cs code below. I get a runtime error "Datatype Mismatch." I dont know how that could be possible considering I am trying to copy these tables into another database with the exact same setup.

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

            }          
        }

Why am I getting this error? Both tables are exactly the same. What am I doing wrong?
Worst case, how do I delete the table in the other Access .MDB file before inserting the exact same structure table with different values in it?

Man I wish I could just figure this out...

EDIT:

Okay, I've come some distance. My question has morphed into a new one, and thus deserves being asked seperately. I have had my question answered as now I know how to execute queries directly to the connection that I have opened. Thank you all!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

无所谓啦 2024-07-21 00:14:19

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

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

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

I'm not sure how far you've gotten, but if you looking for a quick drag and drop operation you might want to look at creating a strongly-typed dataset that connects, and using the drag-drop features of the DataSources Tool Window in Visual Studio.

There are definately samples out there, but you will want to.

  1. Create a new DataSet
  2. Drag-n-Drop from your DataConnection Tree in Server Explorer
  3. Create a new form
  4. Drag the table from the DataSources Tool
  5. Window on to the form.
  6. voila

Update:

First off, I'm not 100% that I understand your issue. If you can create some LinkTables between the access files that would be best, then you can copy the data between files using a sql statement like 'INSERT INTO Customers SELECT FirstName, LastName FROM File2.Customers'. If thats not and option I think your going to have to loop the DataTables and insert the records manually using INSERT statements similar to your last edit. As for the datagrid, you will probably have to keep track of whats changed by monitoring the RowChanged Event (not sure if thats the exact event) of even do the insert/update statements when the row changes.

Update:

to loop the datatable you would do something like this. not tested. I just updated this again to include the MakeValueDbReady function. This is not tested either and I'm not sure if I've handle all the cases or even all the cases correctly. You'll really have to debug the sql statement and make sure its generating the right value. Each database handles is values differently. Atleast this way the value parse is extracted away. I also realized that instead of hard coding the TableName you should be able to get it from a property on the DataTable

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();
    }
}
芸娘子的小脾气 2024-07-21 00:14:19

要使用对数据集(不是 DataGrid,因为这只是数据集上的 UI)所做的更改来更新原始 MDB 文件,只需使用 DataAdapter.Update 命令。

将表从 1 移动到另一个有点棘手。 如果目标中尚不存在该表,则需要使用 SQL CREATE 语句。 然后,DataAdapter.Fill 来自源的数据集< /em>. 循环遍历每一行,并通过调用 将其状态设置为 RowAdded DataRow.SetAdded。 然后,将其从目标数据库传递回DataAdapter.Update。

编辑:代码是下一个问题......

To update the original MDB file with changes made to the DataSet (not the DataGrid, since that's just UI over the DataSet) just use the DataAdapter.Update command.

To move tables from 1 to the other is a bit trickier. If the table doesn't already exist in the destination, you'll need to create it using a SQL CREATE statement. Then, DataAdapter.Fill a DataSet from the source. Loop through each row and set it's state to RowAdded by calling DataRow.SetAdded. Then, pass it back to a DataAdapter.Update from the destination database.

EDIT: Code is on the next question....

喜爱皱眉﹌ 2024-07-21 00:14:19

实际上,具有 .mdb 扩展名的文件格式不止一种。 所以,如果我猜错了,这就是错误的答案。 但是,这听起来像是 Microsoft Access 问题。

您不直接写入 MDB 文件。 它们被加密和压缩。 修改 MDB 文件的最简单方法是通过 Access 加载它并通过提供的方法复制表。

There are actually more than one format of file with the .mdb extension. So, if I guess the wrong one, this will be the wrong answer. But, it sounds like a Microsoft Access issue.

You don't write directly to an MDB file. They are encrypted and compressed. The easiest way to modify an MDB file is to load it through Access and copy the tables through the methods provided.

笑叹一世浮沉 2024-07-21 00:14:19

您如何连接到数据库(.mdb 文件)? 你能发布一些示例代码吗? 如果您正确连接到它,那么您对其运行的任何 SQL 操作都应该自动保存在数据库中。

因此,连接到数据库后,您可以执行 SQL 来创建表、插入/更新/检索数据等。不建议尝试手动构建 .mdb 文件。

这是一个示例:

http://www.java2s.com/代码/CSharp/Database-ADO.net/Access.htm

How are you connecting to the database (the .mdb file)? Could you post some sample code? If you're connecting to it correctly than any SQL operations you run against it should be saved in the database automatically.

So after you connect to the database you can execute SQL that will create tables, insert/update/retrieve data, etc. Trying to build an .mdb file by hand is not advisable.

Here's an example:

http://www.java2s.com/Code/CSharp/Database-ADO.net/Access.htm

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文