c# postgresql npgsql

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 :

  1. Rellene la DataTable que se utilizará para la actualización.
  2. Elimina la fila con Code = 1101 (por ejemplo) directamente de la base de datos, es decir, no utiliza la DataTable aquí. Esto está emulando a otro usuario eliminando la fila con Code = 1101 de otra aplicación. O alguna otra parte en su código eliminando la fila con Code = 1101 .
  3. Selecciona la fila con Code = 1101 de la DataTable , esto es solo para mostrar que todavía está allí aunque la haya eliminado de la base de datos.
  4. Edita la columna Quantity en la fila con Code = 1101 en la DataTable . Esto debe hacerse, de lo contrario, la llamada a Actualizar ignorará esta fila al actualizar.
  5. 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?