从具有新添加的行状态的 DataGridView 将数据插入 SQL


dtNew = TryCast(bs.DataSource, DataTable).GetChanges()
If (dtNew IsNot Nothing) Then
For Each dr As DataRow In dtNew.Rows
Select Case (dr.RowState)
Case DataRowState.Added
Dim strSQLDelete As String = String.Empty
strSQLDelete = String.Format("insert into employeebenefittran (empbenefitcode,amount,calamount,refno,taxclass,source,empbenefitdate,period,cycle,empno) values ('{0}',{1},{1},'{2}','{3}','{4}','{5}','{6}','{7}','{8}')", dr(0), dr(1), "", dr(2), "Y", Date.Parse(String.Format("{0}-{1}-{2}", strPeriod.Substring(0, 4), strPeriod.Substring(4, 2), 1)), strPeriod, "0E", strEmpNo)
Using sqlConn As New SqlConnection(sDBConnection)
If sqlConn.State = ConnectionState.Closed Then sqlConn.Open()
Using cmdSQLDelete As New SqlClient.SqlCommand(strSQLDelete, sqlConn)
cmdSQLDelete.ExecuteNonQuery()
End Using
If sqlConn.State = ConnectionState.Open Then sqlConn.Close()
End Using
End Select
Next
End If

我已经编码为使用数据源从DataGridView插入我新添加的数据。但是,我发现在完成一行数据键入后,我总是需要单击下一行,否则它将发现我的数据源或数据表没有任何内容并跳过插入。 * 意味着 dtNew 将永远一无所有,直到我单击数据网格视图上的新行,这不是一个好的用户体验。

你对此有什么想法吗?

您应该将DataTable绑定到BindingSource,然后将其绑定到网格。 看来您可能已经在这样做了。 然后,您可以在准备好保存时在BindingSource上调用EndUpdate,这会将任何挂起的更改提交到基础DataTable

至于实际的节省,您正在使非常简单的事情复杂化。 首先,您不需要该Select CaseGetChanges方法允许您指定一个或多个DataRowState值,生成的DataTable将仅包含具有该状态的已更改行。 更改此设置:

dtNew = TryCast(bs.DataSource, DataTable).GetChanges()

对此:

dtNew = TryCast(bs.DataSource, DataTable).GetChanges(DataRowState.Added)

然后你可以删除Select Case.

顺便说一句,您永远不应该使用TryCast然后将另一个成员链接到它。TryCast的全部意义在于它可以返回Nothing. 如果代码中发生这种情况,则会抛出NullReferenceExcpetion。 如果你知道这永远不会发生,那么你首先应该使用DirectCast而不是TryCast

也没有充分的理由使用这样的循环。 您应该使用适当的InsertCommand创建数据适配器,然后将DataTable传递给其Update方法。 这会将该DataTable中的所有更改保存为批处理。

无论如何,可能没有充分的理由打电话给GetChanges。 仅当可能存在您不想同时保存的添加以外的类型的更改时,才会执行此操作。 如果要保存所有更改或只能有新行,则不妨在数据适配器上调用Update并传递原始DataTable

最新更新