无法使用 adapter.update 命令根据绑定到 gridview 的数据表中的更改更新数据库

cant get the database updated based on changes in datatable bound to gridview using adapter.update command

我正在使用两个带有按钮的网格视图来交换两者之间的行。现在我要做的是,对 gridviews 进行更改,尝试将它们转换为数据 tables,然后使用 dataadapter.update(datatable) 命令更新数据库。但这些变化不会发生在数据库中。这是我的代码。提前致谢。

Private Sub SubmitToDbButton_Click(sender As Object, e As EventArgs) Handles SubmitToDbButton.Click
    Dim con As New SqlConnection
    Dim dt1 As New DataTable
    Dim dt2 As New DataTable
    Dim ds As New DataSet
    Dim da1 As New SqlDataAdapter("Select * from Table_1", con)
    Dim builder1 As New SqlCommandBuilder(da1)
    Try
        con.ConnectionString = "Data Source=N0PCRIM9L3RYX1;Initial Catalog=RandomFormDB;Integrated Security=True"
        con.Open()
        da1.Fill(dt1)
        dt1 = TryCast(DataGridView1.DataSource, DataTable) 'datatable gets new rows here
        dt1.AcceptChanges()
        da1.Update(dt1)
        con.Close()
    Catch ex As System.Data.SqlClient.SqlException
        MsgBox(ex.Message)
    End Try
End Sub

这是完整的代码。我是 vb 的新手,所以这真的很想念我。从查询返回的 datatable 和 table 具有相同的列。但不知何故,dataadapter 无法理解这一点。怎么做?

Imports System.Data.SqlClient
Public Class Form1
    Dim L As Load_Data
    Public Sub LoadButton_Click(sender As Object, e As EventArgs) Handles LoadButton.Click
        L = New Load_Data()
        L.Load()
    End Sub

    Private Sub LTRButton_Click(sender As Object, e As EventArgs) Handles LTRButton.Click       
        Dim dt1 As DataTable   'moves selected row from left gridview to right one
        Dim dt2 As DataTable
        Dim str As String = Nothing
        dt1 = TryCast(DataGridView1.DataSource, DataTable)
        dt2 = TryCast(DataGridView2.DataSource, DataTable)
        Dim selecetedId As String = DataGridView1.SelectedRows(0).Cells(1).Value
        Dim row As DataRow
        For Each row In dt1.Rows
            If row.Item("ID") = selecetedId Then
                dt2.ImportRow(row)
                dt1.Rows.Remove(row)
                Exit For
            End If
        Next
    End Sub

    Private Sub RTLButton_Click(sender As Object, e As EventArgs) Handles RTLButton.Click          
        Dim dt1 As DataTable  'moves selected row from right gridview to left one
        Dim dt2 As DataTable
        Dim str As String = Nothing
        dt1 = TryCast(DataGridView1.DataSource, DataTable)
        dt2 = TryCast(DataGridView2.DataSource, DataTable)
        Dim selecetedId As String = DataGridView2.SelectedRows(0).Cells(1).Value
        Dim row As DataRow
        For Each row In dt2.Rows
            If row.Item("ID") = selecetedId Then
                dt1.ImportRow(row)
                dt2.Rows.Remove(row)
                Exit For
            End If
        Next
    End Sub

    Private Sub SubmitToDbButton_Click(sender As Object, e As EventArgs) Handles SubmitToDbButton.Click
        Dim con As New SqlConnection  'this sub submits changes to database
        Dim dt1 As New DataTable      'problem lies in this function
        Dim dt2 As New DataTable
        Dim ds As New DataSet
        Dim da1 As New SqlDataAdapter("Select * from Table_1", con)
        Dim builder1 As New SqlCommandBuilder(da1)
        Try
            con.ConnectionString = "Data Source=N0PCRIM9L3RYX1;Initial Catalog=RandomFormDB;Integrated Security=True"
            con.Open()
            da1.Fill(dt1)
            dt1 = TryCast(DataGridView1.DataSource, DataTable)
            'dt1.AcceptChanges()
            da1.Fill(dt1)
            da1.Update(dt1)
            con.Close()
        Catch ex As System.Data.SqlClient.SqlException
            MsgBox(ex.Message)
        End Try
    End Sub
End Class

Public Class Load_Data
    Public Sub Load()
        Dim con As New SqlConnection
        Dim da As New SqlDataAdapter("Select * from Table_1; Select * from Table_2", con)
        Dim ds As New DataSet()
        Try
            con.ConnectionString = "Data Source=N0PCRIM9L3RYX1;Initial Catalog=RandomFormDB;Integrated Security=True"
            con.Open()
            da.Fill(ds)
            Form1.DataGridView1.DataSource = ds.Tables(0)
            Form1.DataGridView2.DataSource = ds.Tables(1)
        Catch ex As System.Data.SqlClient.SqlException
            MsgBox(ex.Message)
        End Try
        con.Close()
    End Sub
End Class

你需要在 table 加载后填充适配器,因此

     da1.Fill(dt1)
    dt1 = TryCast(DataGridView1.DataSource, DataTable) 'datatable gets new rows here


应该改为

    dt1 = TryCast(DataGridView1.DataSource, DataTable)
     da1.Fill(dt1)

AcceptChanges 的调用对数据表的行产生了这种影响。

具有 RowState set to something different from DataRowState.Unchanged 的每一行都将设置为 DataRowState.Unchanged,但具有 DataRowState.Deleted 的行将从 table 中删除。

如果您在调用 AcceptChanges 之后调用 Adapter 的 Update 方法,那么您实际上消除了更新数据源的任何可能性。 属性 告诉您的 Update 方法哪些行需要更新已被重置。

因此,要解决您的问题,只需删除 AcceptChanges 调用即可。 但是还有一个问题。当 SqlDataAdapter 绑定到第一个 table(您使用 SELECT * FROM Table_1 加载的那个)时,您已经创建了一个 SqlCommandBuilder,现在您正在尝试更新一个不同的 table可能具有不同的名称和不同的列。所以你的更新命令注定失败。

看来您需要重建 SqlDataAdapter 或使用您用来填充 DataGridView1

的那个

编辑
查看您更新后的代码,我发现了两个问题。
第一个很容易解决,只需删除对 Fill in your Submit code

的双重调用
Dim da1 As New SqlDataAdapter("Select * from Table_1", con)
Dim builder1 As New SqlCommandBuilder(da1)
Try
    con.ConnectionString = "...."
    con.Open()
    dt1 = TryCast(DataGridView1.DataSource, DataTable)
    da1.Update(dt1)
    con.Close()
Catch ex As System.Data.SqlClient.SqlException
    MsgBox(ex.Message)
End Try

第二个问题比较复杂。当您单击以将一行从一个网格移动到另一个网格时,您使用两种方法使您的数据源(datatables)保持不变。 ImportRow and Remove,如果您仔细查看文档,都会对所涉及的行的 RowState 产生影响,使更新处于无法更新任何内容的状态。

你应该尝试使用

....
For Each row In dt2.Rows
    If row.Item("ID") = selecetedId Then
        dt1.LoadDataRow(row.ItemArray)
        row.Delete()
        Exit For
    End If
Next
....

如果您尝试将一行从第二个网格移回到第一行,这种方法可能会导致其他问题,但现在我没有条件对此进行测试。如果您在访问已删除的行时遇到错误,那么您应该添加一个检查来验证加载的行是否不在已删除行的集合中(使用 GetChanges 方法)。