#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
привязано к aDataGridView
, то в таблице вы видите данные, хранящиеся в таблице. Любые изменения, которые вы вносите в сетку, ДОЛЖНЫ быть внесены в таблицу. При вызове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