使用数据适配器更新记录时出现并发错误

这是我的表:

学生StudentId int PK autoincrement,Name varchar(20)

当我尝试更新上次添加的记录时,我发现错误:

错误Concurrency violation: the UpdateCommand affected 0 of the expected 1 records.

这是我的代码:

 using (var connection = new SqlConnection("MyConnectionstring")) { connection.Open(); SqlDataAdapter adapter = new SqlDataAdapter(); SqlCommandBuilder builder = new SqlCommandBuilder(adapter); adapter.SelectCommand = new SqlCommand("select * from Student", connection); DataTable dt = new DataTable(); adapter.Fill(dt); DataRow row = dt.NewRow(); row["Name"] = "Abc"; dt.Rows.Add(row); var addedRecords = dt.GetChanges(DataRowState.Added); adapter.Update(dt); dt.AcceptChanges(); DataRow lastRow = dt.Rows[dt.Rows.Count - 1]; row["Name"] = "Pqr"; adapter.Update(dt); //Error Here connection.Close(); } 

任何人都可以告诉我为什么会发生这种情况以及这个问题的解决办法是什么?

如使用CommandBuilders MSDN创建命令主题中所述,命令构建器生成的自动命令不会检索插入记录的标识字段:

您可能希望将输出参数映射回DataSet的更新行。 一个常见任务是从数据源检索自动生成的标识字段或时间戳的值。 默认情况下,DbCommandBuilder 不会将输出参数映射到更新行中的列。 在这种情况下,您必须明确指定您的命令。

查看“ 检索身份或自动编号值”主题,事实certificate基本上您需要手动生成插入命令。

以下是如何为表执行此操作(请参阅代码中的注释):

 using (var connection = new SqlConnection("MyConnectionstring")) { connection.Open(); // Create data adapter with the specified SelectCommand var adapter = new SqlDataAdapter("select * from Student", connection); // Build InsertCommand var insertCommand = new SqlCommand( "insert into Student (Name) values (@Name) SET @Id = SCOPE_IDENTITY()", connection); insertCommand.Parameters.Add("@Name", SqlDbType.VarChar, 20, "Name"); var parameter = insertCommand.Parameters.Add("@Id", SqlDbType.Int, 0, "StudentId"); parameter.Direction = ParameterDirection.Output; insertCommand.UpdatedRowSource = UpdateRowSource.OutputParameters; adapter.InsertCommand = insertCommand; // Auto build outher commands var builder = new SqlCommandBuilder(adapter); // Read the data var dt = new DataTable(); adapter.Fill(dt); // Insert a new record var row = dt.NewRow(); row["Name"] = "Abc"; dt.Rows.Add(row); adapter.Update(dt); // Update the just inserted record row["Name"] = "Pqr"; adapter.Update(dt); connection.Close(); } 

当您执行第一次更新时,该行将写入数据库,并根据AUTOINCREMENT获取主键。 但是, DataTable中的行不会反映更改的ID。 因此,当您尝试执行第二次更新时,它无法找到您要更新的行(数据表中的ID与数据库中的ID不匹配)。 因此,您会收到并发错误。

这就是为什么,为了将ID放入DataTable ,您需要在进行第二次更新之前刷新DataTable的内容。

要刷新DataTable ,请调用:

 adapter.Fill() 

有关更多信息,请阅读合并数据集内容 。