【发布时间】:2016-06-07 04:13:11
【问题描述】:
我使用 OleDbDataAdapter 和 OleDbCommandBuilder 用数据库内容填充 DataSet 对象,然后根据我在 DataSet 中所做的更改更新数据库。问题是我得到了异常:“并发冲突:UpdateCommand 影响了预期的 1 条记录中的 0 条”。我找到了这个错误的解释:
因为记录可能在返回后已被修改 SELECT 语句,但在 UPDATE 或 DELETE 语句之前 发出,自动生成的 UPDATE 或 DELETE 语句 包含一个 WHERE 子句,指定仅当行更新时 包含所有原始值并且尚未从数据中删除 资源。自动生成的更新尝试更新 已删除或不包含原始值的行 在 DataSet 中发现,该命令不会影响任何记录,并且 抛出 DBConcurrencyException。
这意味着自动生成的 UPDATE 命令影响了数据库中的 0 行。我使用 paradox(db-file) 数据库,除了我之外没有人改变它。我猜我的程序在某个地方两次更改了同一行。我想通过手动执行所有生成的查询并找到哪个不影响任何行来调试我的程序(因为实际上我很确定所有更改只进行一次并且错误在其他地方)))。是否可以手动运行自动生成的命令?
我的代码太大太复杂,无法在这里发布,但通常它是这样工作的(我做了一个工作项目并从那里拿走它)
using System;
using System.Data;
using System.Windows.Forms;
using System.Data.OleDb;
namespace OleDBCommandBuilder
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string cs = @"Provider=Microsoft.Jet.OLEDB.4.0;";
cs += @"Data Source=C:\FOLDER\1\SPR_KMZ\;";
cs += @"Extended Properties=Paradox 5.x;";
OleDbConnection Connection = new OleDbConnection();
Connection.ConnectionString = cs;
try
{ Connection.Open(); }
catch (Exception ex)
{ MessageBox.Show("Error openning database! " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); Environment.Exit(0); }
string SQLQuery = "SELECT * FROM SPR_KMZ WHERE REZ<>0";
DataSet SPR_KMZ = new DataSet();
OleDbDataAdapter DataAdapter = new OleDbDataAdapter();
DataAdapter.SelectCommand = new OleDbCommand(SQLQuery, Connection);
OleDbCommandBuilder builder = new OleDbCommandBuilder(DataAdapter);
try
{
DataAdapter.Fill(SPR_KMZ);
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(String.Format("Error \n{0}\n{1}", ex.Message, SQLQuery));
Environment.Exit(0);
}
DataRow[] SPR_KMZ_rows = SPR_KMZ.Tables[0].Select("Fkmz=10000912 AND REZ=1");
foreach (DataRow SPR_KMZ_row in SPR_KMZ_rows)
{
SPR_KMZ_row["DN"] = Convert.ToDateTime("30.12.1899");//26.12.2008
SPR_KMZ_row["Price"] = Convert.ToDouble(0);//168,92
}
DataAdapter.Update(SPR_KMZ);
System.Windows.Forms.MessageBox.Show("Success!");
Environment.Exit(0);
}
}
}
附:以前它更新数据库没有并发异常,但是经过很多更改(我出于调试原因将“DataAdapter.Update(SPR_KMZ);”这行注释掉了很长时间,所以我不知道这个错误究竟是什么时候开始的扔)
附言我的代码中没有插入或删除,只有更新...
>
我发现了问题所在:如果“DN”字段的值为 NULL,那么在更改它之后,自动生成的 UPDATE 语句不会影响任何内容,显然是因为“DN”包含在主键和命令中builder 没想到主键字段有 NULL 值(谁曾经会))),毫不奇怪这个引擎被称为“悖论”)))
这就是为什么
CommandBuilder.GetUpdateCommand().CommandText
在“DN”字段的where子句中有这种模式:
... WHERE ((REZ = ?) AND (DN = ?) AND ...
虽然可空字段是这样描述的:
... AND ((? = 1 AND Price IS NULL) OR (Price = ?)) AND ((? = 1 AND Nmed IS NULL) OR (Nmed = ?)) AND ...
P.S.S.S.嘿,我可以尝试手动设置 UpdateCommand 来解决这个问题!)))
【问题讨论】:
-
是否有可能包含您正在使用的代码?
-
搜索缺失的插入语句或删除语句。是否可以通过减少 DataSet 突变的数量来减少您的问题?