VB.NET与数据库问题:首次扫描无IN记录,需生成空entry_record
问题分析与修复方案
问题根源
首次扫描时,monitoring表中不存在当前id_num的记录,第二个查询的dr.Read()返回False,导致While循环完全不执行。此时record变量保持初始空值,status.Text也未被赋值,最终插入数据库时entry_record字段就为空(NULL)。只有当表中已有记录时,循环才会触发,record才会被正确赋值,插入行为才正常。
另外还有两个潜在问题:
- 查询
monitoring表时如果存在多条同id_num的记录,While循环会反复覆盖record的值,最终只会保留最后一条记录的判断结果,逻辑不准确,应该取最新的一条记录来判断出入状态。 - 初始未给
record设置默认值,没有兜底逻辑。
修复后的代码
Private Sub TextBox7_KeyDown(sender As Object, e As KeyEventArgs) Handles TextBox7.KeyDown If e.KeyCode = Keys.Enter Then Dim idnum = TextBox7.Text ' 初始化默认值为IN,兜底首次扫描的情况 Dim record As String = "IN" TextBox2.Text = "" TextBox3.Text = "" TextBox4.Text = "" ' 获取学生信息 ConnectToDB() sql = "select * from rfidmaintest.student_details_dub where f9 = @idnum" cmd = New MySqlCommand(sql, cn) cmd.Parameters.AddWithValue("@idnum", idnum) dr = cmd.ExecuteReader While dr.Read TextBox2.Text = dr("f2").ToString() TextBox3.Text = dr("f9").ToString() TextBox4.Text = dr("f4").ToString() TextBox5.Text = dr("f14").ToString() TextBox6.Text = dr("f3").ToString() TextBox7.Clear() End While dr.Close() cn.Close() ' 查询最新的监控记录,判断出入状态 ConnectToDB() ' 按日期倒序,只取最新一条记录 sql = "select entry_record from rfidmaintest.monitoring where id_num = @idnum order by date desc limit 1" cmd = New MySqlCommand(sql, cn) cmd.Parameters.AddWithValue("@idnum", idnum) dr = cmd.ExecuteReader If dr.Read() Then Dim existingRecord As String = dr("entry_record").ToString() If existingRecord = "IN" Then record = "OUT" ElseIf existingRecord = "OUT" OrElse String.IsNullOrEmpty(existingRecord) Then record = "IN" End If End If status.Text = record dr.Close() cn.Close() ' 插入新记录 ConnectToDB() sql = "insert into monitoring (id_num, fname, lname, status, entry_record, floor_level, date) VALUES (@num, @name, @lname, @stat, @record, @lev,@date)" cmd = New MySqlCommand(sql, cn) With cmd .Parameters.AddWithValue("@num", idnum) .Parameters.AddWithValue("@name", TextBox2.Text) .Parameters.AddWithValue("@lname", TextBox6.Text) .Parameters.AddWithValue("@stat", TextBox5.Text) .Parameters.AddWithValue("@lev", levellock.sharevalue) .Parameters.AddWithValue("@record", record) ' 直接用初始化后的record变量,避免依赖控件值 .Parameters.AddWithValue("@date", Date.Now) .ExecuteNonQuery() ' 插入操作应该用ExecuteNonQuery,而不是ExecuteReader End With MsgBox("Details has been saved!", vbInformation, "Saved") cmd.Dispose() cn.Close() End If End Sub
关键修改点
- 初始化默认值:将
record初始化为"IN",确保首次扫描时即使没有历史记录,也能正确赋值。 - 优化查询逻辑:查询
monitoring表时按date倒序并只取最新一条记录,避免多条记录导致的逻辑混乱。 - 替换执行方法:插入操作使用
ExecuteNonQuery()而非ExecuteReader(),符合数据库操作规范(ExecuteReader()用于查询,ExecuteNonQuery()用于增删改)。 - 避免SQL注入:将第一个查询的字符串拼接改为参数化查询,提升安全性。
- 直接使用变量:插入时直接用
record变量,避免依赖控件status.Text的值,减少潜在的控件值异常问题。
内容的提问来源于stack exchange,提问作者user19101467
相关产品推荐
相关产品推荐

