VB.NET中DataTable无法更新或添加行的问题求助
排查VB.NET中DataTable更新/插入数据库失败的问题
嘿,我一眼就看到问题所在了——你只在内存里修改了DataTable,但完全没把这些变更同步回数据库!而且还有个潜在的大问题:直接拼接SQL字符串会导致SQL注入风险,这个得先改掉。
核心问题分析
- 未同步变更到数据库:你调用
dtObj.AcceptChanges()只是告诉DataTable“这些修改我确认了”,但这只是内存操作,根本不会触发任何数据库的更新/插入动作。SqlDataAdapter需要用Update()方法才能把DataTable里的变更写回数据库。 - SQL注入风险:直接把
ScreenName拼进SQL语句里,要是有人输入类似' OR 1=1 --的内容,你的数据库就危险了,必须用参数化查询替代。
修正后的代码示例
下面是修复后的完整代码,我会标注关键改动:
' 改用参数化查询,彻底避免SQL注入 Dim strSQL As String = "SELECT ScreenName, Status FROM ScreenCheckDuplicates WHERE ScreenName = @ScreenName" Dim aObj As New SqlDataAdapter(strSQL, conn) ' 给查询添加参数 aObj.SelectCommand.Parameters.AddWithValue("@ScreenName", ScreenName) Dim dtObj As New DataTable aObj.Fill(dtObj) If dtObj.Rows.Count > 0 Then ' 更新内存中的行数据 dtObj.Rows(0)("Status") = Status Else ' 向内存中的DataTable添加新行 Dim drNew As DataRow = dtObj.NewRow() drNew("ScreenName") = ScreenName drNew("Status") = Status dtObj.Rows.Add(drNew) End If ' 关键步骤:用SqlCommandBuilder自动生成更新/插入命令(前提是表有主键,比如ScreenName是主键) Dim cmdBuilder As New SqlCommandBuilder(aObj) ' 执行更新,把DataTable的变更同步到数据库 aObj.Update(dtObj) ' 最后标记DataTable的变更已提交(这步要放在Update之后) dtObj.AcceptChanges()
关键细节说明
- 参数化查询:用
@ScreenName占位符代替直接拼接字符串,既安全又能处理ScreenName包含单引号等特殊字符的情况。 - SqlCommandBuilder的作用:它会根据你的
SelectCommand自动生成对应的UpdateCommand和InsertCommand,省得你手动写SQL。不过这个工具要求你的表必须有主键(比如ScreenName是主键的话就没问题)。 - Update和AcceptChanges的顺序:一定要先调用
aObj.Update(dtObj)把变更写入数据库,再调用dtObj.AcceptChanges()标记内存中的DataTable为已提交,避免后续重复执行更新。
手动创建命令的场景(如果表没有主键)
如果你的ScreenCheckDuplicates表没有主键,SqlCommandBuilder就无法自动生成命令了,这时候需要手动创建UpdateCommand和InsertCommand:
' 手动创建更新命令 aObj.UpdateCommand = New SqlCommand("UPDATE ScreenCheckDuplicates SET Status = @Status WHERE ScreenName = @ScreenName", conn) aObj.UpdateCommand.Parameters.Add("@Status", SqlDbType.NVarChar, 50, "Status") aObj.UpdateCommand.Parameters.Add("@ScreenName", SqlDbType.NVarChar, 100, "ScreenName") ' 手动创建插入命令 aObj.InsertCommand = New SqlCommand("INSERT INTO ScreenCheckDuplicates (ScreenName, Status) VALUES (@ScreenName, @Status)", conn) aObj.InsertCommand.Parameters.Add("@ScreenName", SqlDbType.NVarChar, 100, "ScreenName") aObj.InsertCommand.Parameters.Add("@Status", SqlDbType.NVarChar, 50, "Status")
这样修改后,不管是更新已有行还是插入新行,数据都会正常同步到数据库里了。
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

