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

Pau*_*i73 1 c# sql oledb syntax-error

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

\n\n
try\n{\n    // Open the database \n    OleDbCommand mySelectCommand = new OleDbCommand(strAccessSelect, myAccessConn);\n    OleDbDataAdapter myDataAdapter = new OleDbDataAdapter(mySelectCommand);\n    OleDbCommandBuilder myCommandBuilder = new OleDbCommandBuilder(myDataAdapter);\n    myAccessConn.Open();\n\n    // Get Analogue table\n    int rowCount = myDataAdapter.Fill(myDataSet, "Analogue");\n    Console.WriteLine("Row Count: " + rowCount);\n    DataTable analogues = myDataSet.Tables["Analogue"];\n    analogues.PrimaryKey = new DataColumn[] { analogues.Columns["Name"] };\n\n    // Create a new row.\n    System.Data.DataRow newRow;\n    newRow = analogues.NewRow();\n    newRow["Name"] = "My new row";\n    newRow["Area"] = "System";\n    newRow["Description"] = "My new row, created by me!";\n\n    analogues.Rows.Add(newRow);\n    myDataAdapter.InsertCommand = myCommandBuilder.GetInsertCommand();\n    myDataAdapter.UpdateCommand = myCommandBuilder.GetUpdateCommand();\n    Console.WriteLine("Insert Command: " + myDataAdapter.InsertCommand.ToString());\n    Console.WriteLine("Update Command: " + myDataAdapter.UpdateCommand.ToString());\n\n    myDataAdapter.Update(myDataSet, "Analogue");\n}\ncatch (Exception ex)\n{\n    Console.WriteLine("Error: Failed to manipulate the DataBase.\\n{0}", ex.ToString());\n    return;\n}\nfinally\n{\n    myAccessConn.Close();\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

为了简洁起见,我从表中删除了大部分列,但所有列标题都用引号引起来,它们都不包含任何空格,也没有保留字。我删除的都不是 Access 关键字,但我注意到 \xe2\x80\x9cNAME\xe2\x80\x9d 和 \xe2\x80\x9cDescription\xe2\x80\x9d 是。我不\xe2\x80\x99t 相信这导致了我的问题,因为我已经能够修改现有行中 \xe2\x80\x9cDescription\xe2\x80\x9d 列中的文本。

\n\n

命令生成器正在为我生成以下内容,这看起来不太正确:

\n\n
System.Data.OleDb.OleDbCommand\n
Run Code Online (Sandbox Code Playgroud)\n\n

我需要手动构建这个命令吗?如果是这样,我应该使用哪个,插入或更新 \xe2\x80\x93 适配器只有一个更新方法,据我了解可以调用更新或插入?

\n\n

这是有错误的堆栈跟踪:

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

Ste*_*eve 5

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

但是,语法错误的根源是 Access 2007 中存在保留字,例如名称和描述。施梅尔特先生已经在其评论中指出,解决方案很简单。

OleDbCommandBuilder myCommandBuilder = new OleDbCommandBuilder(myDataAdapter);
myCommandBuilder.QuotePrefix = "[";
myCommandBuilder.QuoteSuffix = "]";
Run Code Online (Sandbox Code Playgroud)

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

"INSERT INTO [Analogue] ([Name], [Area], [Description], ...) VALUES(?, ?, ?, ...)" 
Run Code Online (Sandbox Code Playgroud)

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