Se ha producido una excepción de DBConcurrency al actualizar con DataDapter

Estoy tratando de editar DataTable llenado por NpgsqlDataAdapter . Después de llamar al método Fill() , tengo solo una fila en DataTable . Luego cambié el valor de una sola columna e intenté actualizar de la siguiente manera.

enter image description here

Entonces estoy obteniendo este error:

Se produjo DBConcurrencyException

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 llamo solo a dos campos en la statement de selección. ¿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. Usé 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ó. DataType de código de columna es varchar. No sé por qué esto estaba pasando. ¿Alguien tiene idea al respecto?

Esto se debe a que DataAdapter utiliza la Optimistic Concurrency de manera predeterminada. Esto significa que si intenta actualizar una fila que ya no existe en la base de datos o que no se ha modificado, la actualización del DataAdapter fallará con la excepción anterior.

Posibles escenarios :

  • Entre la selección de los datos en el cliente y el envío de la actualización, otro usuario está eliminando o actualizando esta fila de su aplicación.
  • Puede ser que esté borrando los datos de otro lugar en su aplicación.

Por ejemplo :

  1. DataTable la DataTable que se usará para la actualización.
  2. Elimina la fila con Code = 1101 (por ejemplo) directamente de la base de datos, es decir, no usa la DataTable aquí. Esto es emular a otro usuario eliminando la fila con Code = 1101 desde otra aplicación. O alguna otra parte en tu código eliminando la fila con Code = 1101 .
  3. Selecciona la fila con Code = 1101 desde DataTable , esto es solo para mostrar que todavía está allí aunque lo haya borrado de la base de datos.
  4. Edita la columna Quantity en la fila con Code = 1101 en DataTable . Esto tiene que hacerse, de lo contrario, la llamada a Actualizar ignorará esta fila cuando se actualice.
  5. Ejecuta la actualización, arrojará la excepción ya que está tratando de actualizar una fila que (ya no existe) en la base de datos.

Si desea implementar 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 el DB, puede causar este error aunque los datos sean los mismos. Esto se debe a un error de redondeo decimal.

Una nota importante : siempre debe usar parameterized queries por cierto. Este tipo de concatenaciones de cadenas están abiertas para SQL Injection .