使用Dataadapter更新时发生DBConcurrency异常

Bun*_*top 6 c# postgresql npgsql

我正在尝试编辑DataTable填充NpgsqlDataAdapter.在调用Fill()方法之后,我只有一行DataTable.然后我只更改了一列的值,并尝试更新如下.

在此输入图像描述

然后我收到这个错误:

发生了DBConcurrencyException

我的代码是:

NpgsqlDataAdapter getAllData = new NpgsqlDataAdapter("SELECT sn,
code,product, unitprice, quantity, InvoiceNo, Date FROM stocktable WHERE Code='" + product + "'
 ORDER BY EDate ASC", DatabaseConnectionpg);
DataTable ds1 = new DataTable();
ds1.Clear();
getAllData.Fill(ds1);

if (ds1.Rows.Count > 0)
{
    ds1.Rows[0]["Quantity"] = qty;// calculated value
}
ds1 = ds1.GetChanges();

NpgsqlCommandBuilder cb = new NpgsqlCommandBuilder(getAllData);
//getAllData.RowUpdating += (sender2, e2) => { e2.Command.Parameters.Clear(); };
//cb.SetAllValues = false;
getAllData.DeleteCommand = cb.GetDeleteCommand();
getAllData.InsertCommand = cb.GetInsertCommand();
getAllData.UpdateCommand = cb.GetUpdateCommand();
int x = getAllData.Update(ds1);
if (x > 0)
{
    ds1.AcceptChanges();
}
Run Code Online (Sandbox Code Playgroud)

编辑:我有三个字段作为主键,我只在select语句中调用两个字段.这是DBConcurrency错误的原因吗?但我能够在SQL Server 2005中使用相同的(三个字段作为主键)参数更新表.

更新:

我找到了解决方案,解决方案是我创建并使用第二个DataAdapter来更新数据.我使用getAllData(NpgSqlDataAdapter)将表填充为

NpgsqlDataAdapter getAllData = new NpgsqlDataAdapter("SELECT 
code,product, unitprice, quantity, InvoiceNo, Date FROM stocktable WHERE Code='" + product + "'
 ORDER BY EDate ASC", DatabaseConnectionpg);
Run Code Online (Sandbox Code Playgroud)

并创建了下一个适配器以更新为

NpgsqlDataAdapter updateadap= new NpgsqlDataAdapter("SELECT sn, quantity FROM stocktable WHERE Code='" + product + "'
 ORDER BY EDate ASC", DatabaseConnectionpg);
NpgsqlCommandBuilder cb = new NpgsqlCommandBuilder(updateadap);
    //getAllData.RowUpdating += (sender2, e2) => { e2.Command.Parameters.Clear(); };
    //cb.SetAllValues = false;
    updateadap.DeleteCommand = cb.GetDeleteCommand();
    updateadap.InsertCommand = cb.GetInsertCommand();
    updateadap.UpdateCommand = cb.GetUpdateCommand();
    int x = updateadap.Update(ds1);
    if (x > 0)
    {
        ......
    }
Run Code Online (Sandbox Code Playgroud)

我尝试了很多,发现NpgsqlDataAdapter有列代码问题.当我忽略它然后它工作.列代码的DataType是varchar.我不知道为什么会这样.有人有想法吗?

Sal*_*ari 5

这是因为默认DataAdapter使用Optimistic Concurrency.这意味着,如果您尝试更新数据库中不再存在或更改的行,则更新DataAdapter将失败,并显示上述异常.

可能的情况:

  • 在您将数据选择到客户端并发送更新之间,另一个用户正在从他的应用程序中删除或更新此行.
  • 可能是您正在从应用程序中的其他位置删除数据.

例如:

  1. 您填写DataTable将用于更新的内容.
  2. Code = 1101直接从数据库中删除(例如)行,即您不使用DataTable此处.这是模拟另一个用户Code = 1101从另一个应用程序中删除该行.或者代码中的其他部分删除行Code = 1101.
  3. Code = 1101从中选择出行DataTable,这只是为了表明它仍然存在,即使您已从数据库本身删除它.
  4. 编辑Quantity的行与列Code = 1101DataTable.必须这样做,否则对Update的调用将在更新时忽略此行.
  5. 执行更新,这将抛出异常,因为您尝试更新数据库中不再存在的行.

如果要实现Last Writer Wins,请添加以下代码:

cb.ConflictOption = ConflictOption.OverwriteChanges;
Run Code Online (Sandbox Code Playgroud)

还有一个可能的事情:如果你在数据库中有Decimal/ numeric作为列,即使数据看起来相同,它们也可能导致此错误.这是由于十进制舍入错误.

一个重要的注意事项:你应该总是使用parameterized queries顺便说一句.这种字符串连接是开放的SQL Injection.