Привязанный datatgridview не сохраняет изменения в tableadapter и, следовательно, не в базу данных

#vb.net #winforms

#vb.net #winforms

Вопрос:

У меня есть datagridview, привязанный к таблице, которая, кажется, работает нормально, но не сохраняет изменения в базе данных. Я использую тот же код, что и в другом проекте, который сохранял изменения, поэтому я сбит с толку. Кроме того, я отладил, и код сохранения вызывается, просто не работает. Код в форме вызывает отдельный класс с бизнес-логикой.

Код в форме ниже:

     Private Sub frmAdminAssign_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        ' Below is generated by Visual Studio when I select my data source for my datagridview
        Credit_adminTableAdapter.Fill(DataSet1.credit_admin) ' Foreign key relationship to table being updated (lookup table).
        LoanTableAdapter.Fill(DataSet1.loan) ' Table being updated

        admin_assign = New AdminAssign()
        admin_assign.FilterUnassigned(dgvAssign, LoanTableAdapter)
    End Sub

    Private Sub dgvAssign_CellEndEdit(sender As Object, e As DataGridViewCellEventArgs) Handles dgvAssign.CellEndEdit
        admin_assign.SaveAssignmentChanges(DataSet1, LoanTableAdapter)
    End Sub
  

Ниже приведен код в классе бизнес-логики, вызываемый сверху:

   Public Sub SaveAssignmentChanges(ByRef data_set As DataSet1, ByRef loan_table_adapter As DataSet1TableAdapters.loanTableAdapter)
        ' Saves changes to DB.
        Dim cmdBuilder As SqlCommandBuilder
        cmdBuilder = New SqlCommandBuilder(loan_table_adapter.Adapter)
        loan_table_adapter.Adapter.UpdateCommand = cmdBuilder.GetUpdateCommand(True)

        Try
            loan_table_adapter.Adapter.Update(data_set)
        Catch unknown_ex As Exception
            Dim error_title As String = "Database Save Error"
            Dim unknown_error As String = $"There was an error saving to the database.{vbNewLine}Error: {unknown_ex.ToString}"
            MessageBox.Show(unknown_error, error_title, MessageBoxButtons.OK, MessageBoxIcon.Warning)
        End Try
    End Sub
  

Данные из datagridview не сохраняются в tableadapter, о чем я узнал, добавив строки ниже в начале второй процедуры:

 Dim x As String = loan_table_adapter.GetData()(0)("note_number") ' Unchanged, check was right row
Dim y As String = loan_table_adapter.GetData()(0)("credit_admin_id") ' Changed in datagridview but still null (get null error)
  

Комментарии:

1. Таких вещей, как «сохранение изменений в tableadapter», не существует. Адаптер таблицы открывает соединение с базой данных и выполняет инструкции SQL через это соединение. Он ни в коем случае не содержит никаких данных, поэтому он никогда не содержит никаких изменений. Данные и, следовательно, изменения содержатся в DataTable . Если это DataTable привязано к a DataGridView , то в таблице вы видите данные, хранящиеся в таблице. Любые изменения, которые вы вносите в сетку, ДОЛЖНЫ быть внесены в таблицу. При вызове Update табличного адаптера эти изменения сохраняются в базе данных.

2. При вызове Update табличного адаптера возможны только три результата. 1: вызов завершается с ошибкой и выдается исключение. 2: вызов завершается успешно и возвращает ноль, что означает, что изменений для сохранения не было. 3: вызов завершается успешно и возвращает ненулевое значение, что означает, что изменений было сохранено так много, и они были сохранены. Что это в вашем случае?

3. Кроме того, вы действительно должны обрабатывать CellValueChanged событие, а не CellEndEdit какой смысл сохранять изменения после сеанса редактирования, если никаких изменений не было сделано?

4. Наконец, прекратите объявлять параметры ByRef метода без причины. ByVal по умолчанию по какой-то причине. Объявляйте параметры только ByRef тогда, когда они должны быть. Если вы не знаете обстоятельств, при которых они должны быть, вам следует изучить. Это намного меньше, чем 1% времени, которое вам нужно.

5. Я думал, что SqlCommandBuilder кажется ненужным, но вот как я это изучил, и это сработало. Простое обновление также работает и наверняка лучше, спасибо. ByRef необходим для datagridview при фильтрации, поскольку я передаю его в другой класс, и то же самое с DataSet1. В противном случае я согласен, что все остальное должно быть ByVal, и дополнительная ссылка ByRef в соответствии с моим ответом вызвала мою проблему.

Ответ №1:

Я понял это, это было связано с процедурой фильтрации, которая находится не выше, где я передал tableadapter по ссылке, когда я должен был передать datatable byval. Итак, связано с одним из комментариев jmcilhinney’s byref vs byval выше. Смотрите Код проблемы ниже:

 Public Sub FilterUnassigned(ByRef dgv_assigned As DataGridView, loan_table_adapter As DataSet1TableAdapters.loanTableAdapter)
        ' Should have passed in DataSet1.loan DataTable ByVal and used it below:
        Dim unassigned_loans As DataView = loan_table_adapter.GetData().DefaultView()
        unassigned_loans.RowFilter = "request_date Is Not Null AND numerated_assigned_user Is Null"
        dgv_assigned.DataSource = unassigned_loans
    End Sub
  

Кроме того, пропуск команд SqlCommandBuilder и мой код все еще работают. Итак, все, что мне нужно, это одна строка в соответствии с jmcilhinney вместо 4 (кроме обработки ошибок), как показано ниже:

  Try
            loan_table_adapter.Update(data_set)
        Catch unknown_ex As Exception
            Dim error_title As String = "Database Save Error"
            Dim unknown_error As String = $"There was an error saving to the database.  Please contact Kevin Strickler to resolve.{vbNewLine}Error: {unknown_ex.ToString}"
            MessageBox.Show(unknown_error, error_title, MessageBoxButtons.OK, MessageBoxIcon.Warning)
        End Try