Text_Changed事件中文本框与数据库值比对同时返回正误问题及优化
问题背景
需要实现文本框输入内容和数据库合法值列表的比对校验:已将数据库查询到的合法OrderCode存入List(Of String)集合,原设计通过for循环遍历集合,值匹配时返回true,不匹配则返回false,当前实现代码如下:
Protected Sub txtSearchOC_TextChanged(sender As Object, e As EventArgs) Handles txtSearchOC.TextChanged Dim listEType As List(Of String) = New List(Of String) Dim eType As String = txtSearchOC.Text Dim strResult As String = "" lblPrefix.Text = "" lblList.Text = "" Dim TypeIDQuery As String = " SELECT a.OrderCode FROM SKU AS a INNER JOIN EnrollmentType AS e ON a.EnrollmentTypeID = e.TypeID INNER JOIN Enrollment AS f ON e.RecID = f.EnrollmentTypeID WHERE f.AccountNumber = '12345'; " Using connEType As New SqlConnection(ConfigurationManager.ConnectionStrings("WarrantyConnectionString").ToString) Using cmdEType As New SqlCommand(TypeIDQuery, connEType) cmdEType.Parameters.Add("@AccountNumber", SqlDbType.VarChar, 15).Value = "12345" connEType.Open() Using sdrEType As SqlDataReader = cmdEType.ExecuteReader While sdrEType.Read listEType.Add(sdrEType("OrderCode").ToString) End While End Using End Using End Using For Each Item As String In listEType strResult &= Item & ", " Next For i = 0 To listEType.Count - 1 If eType = listEType(i) Then lblPrefix.Text = "True" End If If eType <> listEType(i) Then lblList.Text = "Error" End If Next 'lblList.Text = strResult End Sub
通过strResult拼接集合内容验证,数据库的OrderCode值已经被正确拉取到集合中。
故障现象
末尾的For循环逻辑存在异常:
- 输入集合内存在的有效值时,会同时显示匹配成功的「True」提示和不匹配的「Error」提示
- 输入集合内不存在的值时,只会正常显示「Error」提示,符合预期
故障原因
循环是逐一遍历集合内的每一个元素做独立判断,没有在找到匹配项后终止判断流程:
- 当输入值和某一个元素匹配时,会把
lblPrefix设为True,但循环不会停止,会继续遍历剩下的所有元素 - 剩下的元素和输入值必然不相等,此时就会触发不等判断逻辑,把
lblList设为Error,覆盖之前的状态
举个直观的例子:假设合法值集合是["OC001", "OC002", "OC003"],输入OC001:
- 遍历第1个元素:匹配,
lblPrefix被设为True - 遍历第2个元素:
OC001不等于OC002,lblList被设为Error - 遍历第3个元素:
OC001不等于OC003,lblList再次被设为Error
最终两个提示就会同时显示。
另外代码存在一个隐含问题:SQL语句里把AccountNumber写死成了'12345',添加的@AccountNumber参数根本没有被SQL引用,属于无效代码。
优化实现方案
不需要手写循环遍历判断,List(Of String)原生提供了Contains方法可以直接判断值是否存在于集合中,逻辑更简洁也不容易出错,优化后的校验逻辑如下:
' 先把两个标签重置为初始状态 lblPrefix.Text = "" lblList.Text = "" ' 直接用Contains方法判断输入是否在合法集合内 If listEType.Contains(eType) Then lblPrefix.Text = "True" Else lblList.Text = "Error" End If
如果需要忽略输入的大小写差异(比如用户输入小写也能匹配大写的合法值),可以改成:
If listEType.Contains(eType, StringComparer.OrdinalIgnoreCase) Then lblPrefix.Text = "True" Else lblList.Text = "Error" End If
额外的优化建议:
- 把SQL语句里写死的
'12345'替换成参数占位符@AccountNumber,让之前添加的参数生效,避免SQL注入风险,修改后的SQL如下:SELECT a.OrderCode FROM SKU AS a INNER JOIN EnrollmentType AS e ON a.EnrollmentTypeID = e.TypeID INNER JOIN Enrollment AS f ON e.RecID = f.EnrollmentTypeID WHERE f.AccountNumber = @AccountNumber; - 用于拼接调试内容的
strResult循环在正式环境可以删掉,避免不必要的性能消耗。
内容的提问来源于stack exchange,提问作者WhiteGlint
相关产品推荐
相关产品推荐

