c# - Excepción de DBConcurrency ocurrida al actualizar usando Dataadapter
postgresql npgsql (1)
Esto se debe a que
DataAdapter
usa la
Optimistic Concurrency
de forma predeterminada.
Esto significa que si está intentando actualizar una fila que ya no existe en la base de datos o ha cambiado, la actualización del
DataAdapter
fallará con la excepción anterior.
Posibles escenarios :
- Entre que selecciona los datos en el cliente y envía la actualización, otro usuario está eliminando o actualizando esta fila de su aplicación.
- Puede ser que esté eliminando los datos de otro lugar de su aplicación.
Por ejemplo :
-
Rellene la
DataTable
que se utilizará para la actualización. -
Elimina la fila con
Code = 1101
(por ejemplo) directamente de la base de datos, es decir, no utiliza laDataTable
aquí. Esto está emulando a otro usuario eliminando la fila conCode = 1101
de otra aplicación. O alguna otra parte en su código eliminando la fila conCode = 1101
. -
Selecciona la fila con
Code = 1101
de laDataTable
, esto es solo para mostrar que todavía está allí aunque la haya eliminado de la base de datos. -
Edita la columna
Quantity
en la fila conCode = 1101
en laDataTable
. Esto debe hacerse, de lo contrario, la llamada a Actualizar ignorará esta fila al actualizar. - Ejecuta la actualización, esto arrojará la excepción ya que está intentando actualizar una fila que (ya no existe) en la base de datos.
Si desea implementar las
Last Writer Wins
, agregue el siguiente código:
cb.ConflictOption = ConflictOption.OverwriteChanges;
También hay una cosa más posible: si tiene
Decimal
/
numeric
como columnas en la base de datos, pueden causar este error aunque los datos se vean iguales.
Esto se debe a un error de redondeo decimal.
Una nota importante
: por cierto, siempre debe usar
parameterized queries
.
Este tipo de concatenaciones de cadenas están abiertas para la
SQL Injection
.
Estoy tratando de editar
DataTable
Filled por
NpgsqlDataAdapter
.
Después de llamar al método
Fill()
, solo tengo una fila en
DataTable
.
Luego cambié el valor de una sola columna e intenté actualizar como se muestra a continuación.
Entonces recibo este error:
DBConcurrencyException ocurrió
Mi código es:
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();
}
EDITAR:
Tengo tres campos como claves principales y solo estoy llamando a dos campos en la instrucción select.
¿Es motivo de error
DBConcurrency
?
Pero puedo actualizar la tabla con los mismos parámetros (tres campos como clave principal) en SQL Server 2005.
ACTUALIZAR:
Encontré la solución y la solución es que creé y usé el segundo DataAdapter para actualizar los datos. Solía getAllData (NpgSqlDataAdapter) para llenar la tabla como
NpgsqlDataAdapter getAllData = new NpgsqlDataAdapter("SELECT
code,product, unitprice, quantity, InvoiceNo, Date FROM stocktable WHERE Code=''" + product + "''
ORDER BY EDate ASC", DatabaseConnectionpg);
Y también creó el siguiente adaptador para actualizar como
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)
{
......
}
Intenté mucho y descubrí que NpgsqlDataAdapter tenía problemas con el código de columna. Cuando lo omití, funcionó. El tipo de datos del código de columna es varchar. No sé por qué estaba pasando esto. Alguien tiene idea al respecto?