views:

81

answers:

0

My code keeps throwing a DBConcurrencyException ("Concurrency violation: the DeleteCommand affected 0 of the expected 1 records.) when I make a second update to the data table.

The problem actually happens on a table that is linked to a parent table. The two tables, CashReceipts and CashReceiptsApplyTo are displayed on the same winform, and when I delete two cash receipts the update on cash receipt apply to's table fails with the dbconcurrencyexception (the table is updated everytime the binding source [linked to a binding navigator] changes position).

Here is my code:

protected override void saveToDatabase() {
    tblCashReceiptsBindingSource.EndEdit();
    tblCashReceiptsTableAdapter.Update(rentalEaseDataSet.tblCashReceipts);

    //update the datatable
    foreach (DataGridViewRow viewRow in viewApplications.Rows) {
        if (viewRow.Cells[colAppID.Index].Value == null || viewRow.Cells[colApplyTo.Index].Value == null) {
            continue;
        } else if ((int)viewRow.Cells[colAppID.Index].Value == -1) {
            insertNewRow(viewRow);
        } else {
            updateRow(viewRow);
        }
    }

    try {
        tblCashReceiptsApplyToTableAdapter.Update(rentalEaseDataSet.tblCashReceiptsApplyTo);
        //tblCashReceiptsApplyToTableAdapter.Fill(rentalEaseDataSet.tblCashReceiptsApplyTo);                );
    } catch (Exception e) {
        Bitmap bitmap = new Bitmap(this.Width, this.Height);
        this.DrawToBitmap(bitmap, new Rectangle(0, 0, this.Width, this.Height));
        saveScreenshot(this.GetType().FullName, e.Message, bitmap);

        MessageBox.Show("There was an error saving your changes. This means that you should close the form, and re-enter the last Receipt you entered.\n\nPlease report this.");
    }
}

The insertNewRow, and updateRow are simple:

private void updateRow(DataGridViewRow viewRow) {
    //be forgiving
    if ((int)viewRow.Cells[colAppID.Index].Value == -1) {
        insertNewRow(viewRow);
        return;
    }

    //find row in table, if it's not there, crash and burn
    RentalEaseDataSet.tblCashReceiptsApplyToRow updateRow = rentalEaseDataSet.tblCashReceiptsApplyTo.Select("ID = " + viewRow.Cells[colAppID.Index].Value.ToString())[0] as RentalEaseDataSet.tblCashReceiptsApplyToRow;
    updateRow.BeginEdit();
    updateRow.CashReceiptsID = (int)viewRow.Cells[colCashReceipt.Index].Value;
    updateRow.ApplyTo = (int)viewRow.Cells[colApplyTo.Index].Value;
    updateRow.Paid = CurrencyToDecimal(viewRow.Cells[colPaid.Index].Value);
    if (viewRow.Cells[colMemo.Index].Value != null) {
        updateRow.Memo = viewRow.Cells[colMemo.Index].Value.ToString();
    } else {
        updateRow.SetMemoNull();
    }
    updateRow.EndEdit();
}

private void insertNewRow(DataGridViewRow viewRow) {
    //be forgiving
    if ((int)viewRow.Cells[colAppID.Index].Value != -1) {
        updateRow(viewRow);
        return;
    }

    RentalEaseDataSet.tblCashReceiptsApplyToRow newRow = rentalEaseDataSet.tblCashReceiptsApplyTo.NewRow() as RentalEaseDataSet.tblCashReceiptsApplyToRow;
    newRow.CashReceiptsID = (int) viewRow.Cells[colCashReceipt.Index].Value;
    newRow.ApplyTo = (int) viewRow.Cells[colApplyTo.Index].Value;
    newRow.Paid = CurrencyToDecimal(viewRow.Cells[colPaid.Index].Value);
    if (viewRow.Cells[colMemo.Index].Value != null) {
        newRow.Memo = viewRow.Cells[colMemo.Index].Value.ToString();
    }
    rentalEaseDataSet.tblCashReceiptsApplyTo.Rows.Add(newRow);

    //update the ID
    viewRow.Cells[colAppID.Index].Value = newRow.ID;
}

Any idea why it would throw that error on the second delete?