Mam więc ten datagridview, który jest powiązany ze źródłem wiążącym, które jest wiążące do podstawowej tabeli danych. Problem polega na ręcznym dodawaniu wierszy do datagridview.Databoving woes
Nie można tego zrobić, gdy jest on związany, więc muszę pracować z bazą danych.
Jeśli dodaję wiersze do bazowego obiektu datatable, po zapisaniu datownika wiersze zostaną zduplikowane, prawdopodobnie dlatego, że źródło powiązania w jakiś sposób dostało kopię i wstawiło je również.
Dodanie tego do wiążącego źródła jest tym, co próbowałem zrobić, ale nie działa.
Pozwól mi wyjaśnić dokładnie, co moja konfiguracja jest:
Mam bazę danych z dwóch tabel: CashReceiptTable i CashReceiptItemsTable
CashReceiptItemsTable zawiera FK do CashReceiptTable.
Formularz umożliwia dodawanie i modyfikowanie dwóch tabel.
Gdy użytkownik wprowadzi nową wartość kasową, identyfikator kasowy ma wartość -1, a wartość FK w polu cashReceiptitemstable wynosi -1. Gdy baza danych zostanie zapisana, identyfikator cashReceipt zostanie zaktualizowany i muszę ręcznie zaktualizować FK cashreceiptitem.
Oto problemy:
Kiedy próbuję zaktualizować CashReceiptID (FK) w więcej niż jednym rzędzie w cashreceiteitems wiążących źródła, pierwszy wiersz jest aktualizowany, i znika (bo jest filtrowane), a inne wiersze są usuwane i nie mogę już uzyskać do nich dostępu.
Nie mam pojęcia, dlaczego tak jest, nie zaktualizowałem jeszcze filtru, więc powinny nadal tam być, ale próba dostępu do nich powoduje odrzucenie wyjątku RowNotInTableException.
Udało mi się obejść, które kopiuje wiersze w źródle wiązania do tablicy w pamięci, usuwa pierwszy wiersz w źródle powiązania (wszystkie pozostałe wiersze po prostu znikają), aktualizuje FK wiersza i ponownie je umieszcza do źródła wiążącego i zapisz tabelę.
To działa dobrze, ale dlaczego rzędy znikają?
Mam również jeszcze jeden niewielki problem. Kiedy CashReceiptsTable jest pusta i dodaję do niej nowy wiersz, jeśli dodaję więcej niż jeden wiersz do CashReceiptsItemTable, powoduje to problemy. Podczas ręcznego dodawania elementów do źródła powiązania dodanie nowego wiersza powoduje przejście do poprzedniego wiersza i przeniesienie go do elementu datatable. To ukrywa ją przed moją procedurą aktualizacji FK i jest tracona, a także usuwa ją z DataGridView.
To tylko robi to, gdy dodaję pierwszy wiersz do CashReceiptsTable. Dlaczego to robi i jak mogę to naprawić?
jestem delegowania mój kod, który autopopulates tutaj:
private void autopopulate(decimal totalPayment) {
//remove old rows
for (int i = 0; i < tblCashReceiptsApplyToBindingSource.List.Count; i++) {
DataRowView viewRow = tblCashReceiptsApplyToBindingSource.List[i] as DataRowView;
RentalEaseDataSet.tblCashReceiptsApplyToRow row = viewRow.Row as RentalEaseDataSet.tblCashReceiptsApplyToRow;
if (row.CashReceiptsID == this.ReceiptID) {
tblCashReceiptsApplyToBindingSource.List.Remove(viewRow);
i--;
}
}
decimal payment = totalPayment;
//look for an exact amount
foreach (DataGridViewRow dueRow in dataViewDueRO.Rows) {
decimal due = -1 * (Decimal)dueRow.Cells[Due.Index].Value;
if (due == payment) {
String charge = (String)dueRow.Cells[Description.Index].Value;
int chargeID = ManageCheckbooks.findTransactionID(charge);
tblCashReceiptsApplyToBindingSource.AddNew();
RentalEaseDataSet.tblCashReceiptsApplyToRow row = ((DataRowView)tblCashReceiptsApplyToBindingSource.Current).Row as RentalEaseDataSet.tblCashReceiptsApplyToRow;
row.CashReceiptsID = this.ReceiptID;
row.ApplyTo = chargeID;
row.Paid = payment; //convert to positive
payment = 0;
break;
}
}
//if the exact amount was found, payment will = 0, and this will do nothing, otherwise,
//divy out everything left over (which will be everything)
foreach (DataGridViewRow dueRow in dataViewDueRO.Rows) {
String charge = (String)dueRow.Cells[Description.Index].Value;
decimal due = (Decimal)dueRow.Cells[Due.Index].Value;
if (due > 0 || payment <= 0) {
continue;
}
int chargeID = ManageCheckbooks.findTransactionID(charge);
payment += due; //due is negative, so this will subtract how much the user owes
tblCashReceiptsApplyToBindingSource.AddNew();
RentalEaseDataSet.tblCashReceiptsApplyToRow row = ((DataRowView)tblCashReceiptsApplyToBindingSource.Current).Row as RentalEaseDataSet.tblCashReceiptsApplyToRow;
row.CashReceiptsID = this.ReceiptID;
row.ApplyTo = chargeID;
if (payment >= 0) {
//payment is enough to cover this
row.Paid = due * -1; //convert to positive
} else {
//doesn't have enough money to conver this, can only cover partial, or none
row.Paid = (due - payment) * -1; //math:
//money remaining $50, current charge = $60
//payment = 50 + -60 = -10
//row["Paid"] = (-60 - -10) * -1
//row["Paid"] = (-60 + 10) * -1
//row["Paid"] = -50 * -1
//row["Paid"] = 50
}
if (payment <= 0) {
break; //don't conintue, no more money to distribute
}
}
isVirginRow = true;
}
I to jest funkcja, która zapisuje je do bazy danych:
protected override void saveToDatabase() {
tblCashReceiptsBindingSource.EndEdit();
isVirginRow = false;
RentalEaseDataSet.tblCashReceiptsRow[] rows = rentalEaseDataSet.tblCashReceipts.Select("ID < 0") as RentalEaseDataSet.tblCashReceiptsRow[];
int newID = -1;
if (rows.Count() > 0) {
tblCashReceiptsTableAdapter.Update(rows[0]);
newID = rows[0].ID;
}
tblCashReceiptsTableAdapter.Update(rentalEaseDataSet.tblCashReceipts);
//update table
/*foreach (RentalEaseDataSet.tblCashReceiptsApplyToRow row in rentalEaseDataSet.tblCashReceiptsApplyTo.Select("CashReceiptsID = -1")) {
row.CashReceiptsID = newID;
}*/
//update binding source
DataRowView[] applicationsOld = new DataRowView[tblCashReceiptsApplyToBindingSource.List.Count];
RentalEaseDataSet.tblCashReceiptsApplyToRow[] applicationsNew = new RentalEaseDataSet.tblCashReceiptsApplyToRow[tblCashReceiptsApplyToBindingSource.List.Count];
tblCashReceiptsApplyToBindingSource.List.CopyTo(applicationsOld, 0);
for (int i = 0; i < applicationsOld.Count(); i++) {
RentalEaseDataSet.tblCashReceiptsApplyToRow row = applicationsOld[i].Row as RentalEaseDataSet.tblCashReceiptsApplyToRow;
if (row.CashReceiptsID < 0) {
applicationsNew[i] = rentalEaseDataSet.tblCashReceiptsApplyTo.NewRow() as RentalEaseDataSet.tblCashReceiptsApplyToRow;
applicationsNew[i]["ID"] = row.ID;
applicationsNew[i]["CashReceiptsID"] = this.ReceiptID;
applicationsNew[i][2] = row[2];
applicationsNew[i][3] = row[3];
applicationsNew[i][4] = row[4];
//row.Delete();
}
}
for (int i = 0; i < applicationsOld.Count(); i++) {
try {
if ((int)applicationsOld[i].Row["ID"] < 0) {
applicationsOld[i].Row.Delete();
}
} catch (RowNotInTableException) {
break;
}
}
this.tblCashReceiptsApplyToBindingSource.Filter = "CashReceiptsID = " + this.ReceiptID;
foreach (DataRow newRow in applicationsNew) {
if (newRow == null) {
break;
}
tblCashReceiptsApplyToBindingSource.AddNew();
((DataRowView)tblCashReceiptsApplyToBindingSource.Current).Row[0] = newRow[0];
((DataRowView)tblCashReceiptsApplyToBindingSource.Current).Row[1] = newRow[1];
((DataRowView)tblCashReceiptsApplyToBindingSource.Current).Row[2] = newRow[2];
((DataRowView)tblCashReceiptsApplyToBindingSource.Current).Row[3] = newRow[3];
((DataRowView)tblCashReceiptsApplyToBindingSource.Current).Row[4] = newRow[4];
}
tblCashReceiptsApplyToBindingSource.EndEdit();
checkForBadRows();
tblCashReceiptsApplyToTableAdapter.Update(rentalEaseDataSet.tblCashReceiptsApplyTo);
tblCashReceiptsApplyToTableAdapter.Fill(rentalEaseDataSet.tblCashReceiptsApplyTo);
}
Mam problem, który moim zdaniem jest w zasadzie taki sam. Myślę, że ogólny problem: Jak dokonać zmian w DataTable, bez bałagan DataView, który jest związany w interfejsie użytkownika? –
Czy kiedykolwiek otrzymałeś rozwiązanie w tej sprawie? –