无法使用 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 方法)。
我正在使用两个带有按钮的网格视图来交换两者之间的行。现在我要做的是,对 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 方法)。