2010-02-15 10 views
7

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); 
    } 
+0

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? –

+0

Czy kiedykolwiek otrzymałeś rozwiązanie w tej sprawie? –

Odpowiedz

1

może chcesz spróbować dodać wiersze do DataGridView.Ponieważ wiążesz go, DataGridView staje się twoim "punktem dostępu".

Mam kilka aplikacji, które wiążą się z DataGridView i dla większości przypadków, kiedy dodać wiersz Czynię to przez DataGridView. Posiada już właściwości/metody/zdarzenia, które umożliwiają względną łatwość dodawania.

Jeśli potrzebujesz trochę więcej informacji mogę zaktualizować.

+0

Stwierdzam w pytaniu, że jeśli dodaję wiersze do DataGridView, duplikuje je w bazie danych. Naprawiłem ten problem dzień po opublikowaniu, ale nie pamiętam, co to była poprawka. – Malfist

+0

Wszystko, co widzę, to "Dodaję wiersze do bazowego obiektu datatable, gdy zapisywane są datatable, wiersze są duplikowane,". Nie widziałem niczego, co mówiłoby o datagridview i duplikowaniu, ale mógłbym tego przegapić. –

+0

Musiałem pomyśleć o innym problemie, który miałem. Przepraszam, przechodząc przez mój kod, stwierdziłem, że zmieniłem go z dodawania wiersza do zestawu danych, aby dodać wiersz do datagridview, więc musiałem wziąć twoją radę. 'ViewApplications.Rows.Add (nowy obiekt [] { -1 this.ReceiptID, chargeID, String.Format ("0 $ {N}" paidThisTime) "" });' – Malfist