2009-02-05 36 views
5

我正在处理的项目已基本完成。我正在加载.MDB文件,在DataGrid上显示内容并尝试在DataGrid上获取这些更改并将它们保存回.MDB文件中。我也将创建一个函数,允许我从一个.MDB文件中获取表并将其保存到另一个.MDB文件。当然,如果我不知道如何将更改保存回.MDB文件,我无法做到这一点。C#问题:我加载.MDB文件,对其进行更改并将更改保存回原始文件的最简单方法是什么?

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

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

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

编辑:

我一起工作的的.mdb是Microsoft Access数据库。(我甚至不知道有多个.mdb文件)

我知道我不能直接写入.MDB文件通过一个Streamwriter或任何东西,但有没有一种方式,我可以用DataSet信息生成一个.MDB文件已经在它? OR是否有一种方法可以将表添加到已经加载到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(); 
} 

正如你所看到的,其实我已经成功地执行连接本身,我认为是实际访问的查询。 MDB文件。正如我所说,我在文件上执行的SQL查询不起作用,并在使用时产生运行时错误。

我试图执行的命令应该从.MDB文件中取出一个表并覆盖同一类型的不同.MDB文件的表。我上面尝试的SQL命令试图直接从.mdb文件中取出一个表,并直接将它放入另一个表中 - 这不是我想要做的。我想从.MDB文件中获取所有信息 - 将表放入一个Datatable中,然后将所有Datatables添加到数据集(我已经完成)。我想为两个.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文件中的表?

男人,我希望我可以想出解决办法...

编辑:

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

+0

@Remou:想在这里得到你的注意 - 你是一个糟糕的情况变得更糟。访问!= MDB。所有这些您从MDB重新标记为MS-ACCESS的问题根本不涉及Access,而只涉及Jet/ACE数据库引擎。我正在重新标记。 – 2009-12-17 05:04:43

+0

@Remou @David W. Fenton:我在meta上提出了这个问题:http://meta.stackoverflow.com/questions/33216/ms-access-or-mdb-or-access-database-engine-or- ms-jet-ace – onedaywhen 2009-12-17 10:37:56

+0

我已经发布在Meta上。 MDB也等于消息驱动的Bean,所以它是一个模糊的标记,并且像Access一样,由于含糊不清而被标记为ms-access,因此需要更改。 – Fionnuala 2009-12-17 11:30:02

回答

3

我不确定你有多远,但是如果你在寻找一个快速的拖放操作,你可能想看看创建一个强类型的数据集来连接,并使用拖放功能Visual Studio中的DataSources工具窗口。

有确定的样品,但你会想。

  1. 从DataConnection树在服务器资源管理器创建一个新的DataSet
  2. 将丁基下降
  3. 从数据源工具上的形式创建一个新的形式
  4. 将表
  5. 窗口。

更新:

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

更新:

循环,你会做这样的事情的数据表。未经测试。我只是再次更新这个包含MakeValueDbReady函数。这还没有经过测试,我不确定我是否已经正确处理所有案件或所有案件。你真的必须调试sql语句并确保它生成正确的值。每个数据库句柄都是不同的值。至少这样,值解析就被提取出来了。我也意识到,而不是硬编码表名,你应该能够得到它的属性在数据表

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

我对我的项目非常满意。我已经具备了编入.MDB文件,显示信息和更改信息的所有功能。我的用户界面已经完成,我只需要一种方法将这些信息返回到一个.MDB文件(或最好是相同的.MDB它来自) – OneShot 2009-02-05 22:54:01

0

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

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

+0

是的我正在使用.mdb文件的Microsoft Access格式。我知道我不直接写入MDB文件。我需要一种方法来插入新表或者生成一个.MDB文件,其中已经包含了信息(比如一个充满表格的数据集)。 – OneShot 2009-02-05 22:52:18

0

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

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

下面是一个例子:

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

1

要更新原有的MDB一起DataSet中所做的更改文件(而不是DataGrid的,因为这在数据集的只是UI)只使用DataAdapter.Update命令。

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

编辑:Code is on the next question....

相关问题