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
How do I structure an OleDbCommand Query so that I can take Tables from one .MDB, and replace them in another .MDB
提问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
我很想知道它是否只是一行抛出错误,或者它是否是查询。我的想法是其中一行有一个时髦的价值