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

Posted

技术标签:

【中文标题】为啥当我调用 DataAdapter.Update() 时,此 C# 代码会生成语法错误?【英文标题】:Why does this C# code generate a Syntax Error when I call DataAdapter.Update()?为什么当我调用 DataAdapter.Update() 时,此 C# 代码会生成语法错误? 【发布时间】:2014-02-05 11:09:10 【问题描述】:

我正在尝试在 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.\n0", 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

【问题讨论】:

请帮忙:***.com/q/19557920/284240 Best Q 是他构建数据集的 SQL 插入语句的形式是什么......有错误 Console.WriteLine(myDataAdapter.InsertCommand.CommandText); 现在您只打印类的名称而不是属性命令文本 什么是mySelectCommand 字符串,您正在使用什么来构建OleDbDataAdapter @Steve 控制台写入的输出是“System.Data.OleDb.OleDbCommand”。我应该使用 .CommmandText 而不是 .ToString 吗? 【参考方案1】:

如果在您的SelectCommand.CommandText 中有一个SELECT * FROM Analogue,那么由OleDbCommandBuilder 构建的InsertCommand 包含每个列的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 属性

【讨论】:

以上是关于为啥当我调用 DataAdapter.Update() 时,此 C# 代码会生成语法错误?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 DataAdapter.Update 啥也不更新?

启动后如何停止执行dataAdapter.update

DataAdapter Update 方法批量更新多行

使用 C# dataAdapter.Fill() 和 dataAdapter.Update() 将表的数据从一个数据库传输到另一个数据库的同一个表

在 DataAdapter.Update/Refresh 后未设置 DataTable 标识列,使用“而不是”触发器(SqlServer 2005)

如何使用 DataAdapter.Update 方法同时更新 Access 数据库和 .NET DataSet 对象?