当我调用DataAdapter.Update()时,为什么这个C#代码会生成语法错误?

时间:2014-02-05 11:09:11

标签: c# sql syntax-error oledb

我正在尝试在C#中的现有MS Access数据库表中添加一个新行。但是,当我调用DataAdapter的Update方法时,我收到“INSERT INTO语句中的语法错误”。我的代码是:

try
{
    // Open the database 
    OleDbCommand mySelectCommand = new OleDbCommand(strAccessSelect, myAccessConn);
    OleDbDataAdapter myDataAdapter = new OleDbDataAdapter(mySelectCommand);
    OleDbCommandBuilder myCommandBuilder = new OleDbCommandBuilder(myDataAdapter);
    myAccessConn.Open();

    // Get Analogue table
    int rowCount = myDataAdapter.Fill(myDataSet, "Analogue");
    Console.WriteLine("Row Count: " + rowCount);
    DataTable analogues = myDataSet.Tables["Analogue"];
    analogues.PrimaryKey = new DataColumn[] { analogues.Columns["Name"] };

    // Create a new row.
    System.Data.DataRow newRow;
    newRow = analogues.NewRow();
    newRow["Name"] = "My new row";
    newRow["Area"] = "System";
    newRow["Description"] = "My new row, created by me!";

    analogues.Rows.Add(newRow);
    myDataAdapter.InsertCommand = myCommandBuilder.GetInsertCommand();
    myDataAdapter.UpdateCommand = myCommandBuilder.GetUpdateCommand();
    Console.WriteLine("Insert Command: " + myDataAdapter.InsertCommand.ToString());
    Console.WriteLine("Update Command: " + myDataAdapter.UpdateCommand.ToString());

    myDataAdapter.Update(myDataSet, "Analogue");
}
catch (Exception ex)
{
    Console.WriteLine("Error: Failed to manipulate the DataBase.\n{0}", ex.ToString());
    return;
}
finally
{
    myAccessConn.Close();
}

为了简洁起见,我已从表中删除了大多数列,但所有列标题都在引号中,它们都不包含任何空格,也没有保留字。我删除的所有内容都不是Access关键字,但我注意到“NAME”和“Description”是。我不相信这会导致我的问题,因为我能够修改现有行的“描述”列中的文本。

Command Builder为我生成以下内容似乎不太正确:

System.Data.OleDb.OleDbCommand

我是否需要手动构建此命令?如果是这样,我应该使用哪个,插入或更新 - 适配器只有一个更新方法,据我所知,可以调用更新或插入?

以下是带有错误的堆栈跟踪:

System.Data.OleDb.OleDbException (0x80040E14): Syntax error in INSERT INTO statement.
   at System.Data.Common.DbDataAdapter.UpdatedRowStatusErrors(RowUpdatedEventArgs rowUpdatedEvent, BatchCommandInfo[] batchCommands, Int32 commandCount)
   at System.Data.Common.DbDataAdapter.UpdatedRowStatus(RowUpdatedEventArgs rowUpdatedEvent, BatchCommandInfo[] batchCommands, Int32 commandCount)
   at System.Data.Common.DbDataAdapter.Update(DataRow[] dataRows, DataTableMapping tableMapping)
   at System.Data.Common.DbDataAdapter.UpdateFromDataTable(DataTable dataTable, DataTableMapping tableMapping)
   at System.Data.Common.DbDataAdapter.Update(DataSet dataSet, String srcTable)
   at SystemMonitor.MainWindow.mnuGenerateSMACS6Interface_Click(Object sender, EventArgs e) in c:\iogen\code\MainWindow.cs:line 436

1 个答案:

答案 0 :(得分:3)

如果您的SelectCommand.CommandText中有SELECT * FROM Analogue,则InsertCommand构建的OleDbCommandBuilder包含每列的INSERT列。
如果要从INSERT中删除某些列,则需要自己构建命令。

但是,语法错误的起源是Access 2007中存在保留字,如NAME和DESCRIPTION。解决方案很简单,Mr Schmelter已在其评论中指出。

OleDbCommandBuilder myCommandBuilder = new OleDbCommandBuilder(myDataAdapter);
myCommandBuilder.QuotePrefix = "[";
myCommandBuilder.QuoteSuffix = "]";

这将强制OleDbCommandBuilder构造CommandText以使用适当的前缀和后缀围绕列名和表名进行插入和更新,从而产生类似

的CommandText
"INSERT INTO [Analogue] ([Name], [Area], [Description], ...) VALUES(?, ?, ?, ...)" 

DataAdapter.UpdateCommand执行INSERT / UPDATE / DELETE命令,查看DataTable中已更改的行的DataRow.RowState属性