我正在使用while循环根据第一个组合框选择的值填充第二个组合。然而,正在发生的是,循环只在第二个组合框中显示1个项目,而不是大约20个。如果我在while循环上设置断点,我可以看到所有项目都在计算但只是没有出现在组合框中。
如果有人能指出我的基本新手错误,我将不胜感激。非常感谢
Private Sub cmbCustomer_SelectedIndexChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles cmbCustomer.SelectedIndexChanged
sql = "SELECT * from Departments WHERE Customer = '" & cmbCustomer.Text & "'"
Dim cmd As New OleDb.OleDbCommand
cmd.CommandText = sql
cmd.Connection = oledbCnn
dr = cmd.ExecuteReader
While dr.Read()
If (dr.HasRows) Then
cmbDept.Text = CStr((dr("Name"))) <--- 2nd combobox
End If
End While
cmd.Dispose()
dr.Close()
End Sub
答案 0 :(得分:5)
组合框的Text
属性仅包含为所选项目显示的内容。您需要将项目添加到Items
集合:
cmbDept.Items.Add(CStr(dr("Name")))
组合框,列表框等通过调用ToString()
方法显示项目。因此,甚至不需要调用CStr
:
cmbDept.Items.Add(dr("Name"))
您通过连接字符串在SQL语句中插入值。如果你只是为自己使用你的程序,这是可以的;然而,在生产环境中,这是危险的。有人可以输入一个终止SELECT语句的值,并引入另一个恶意语句。例如。删除整个表的DELETE语句。这称为SQL注入攻击。
有两种方法可以解决这个问题:
1)逃离字符串:
sql = "SELECT * FROM Dep WHERE Cust = '" & s.Replace("'", "''") & "'"
2)使用命令参数:
sql = "SELECT * from Departments WHERE Customer = ?"
Dim cmd As New OleDbCommand(sql, oledbCnn)
cmd.Parameters.AddWithValue("@p1", cmbCustomer.Text)
如果您要插入日期,这也有一个优点,您无需担心日期格式。
您可以将循环简化为:
While dr.Read()
cmbDept.Text = CStr(dr("Name"))
End While
没有必要测试HasRows
,因为如果没有可用的行,dr.Read()
会返回False
。
您可以使用Dispose
语句自动调用Using
:
Using cmd As New OleDbCommand(sql, oledbCnn)
'TODO: Work with cmd here.
End Using
Dispose
将在Using
块的末尾调用,即使Using
块中发生错误或Using
块被{{1}留下或另一种陈述。
答案 1 :(得分:4)
您不需要检查数据读取器是否每次迭代都有行,只需在循环之前检查它。
您不是要将项目添加到列表中,而是设置Text
的{{1}}属性,而是执行此操作:
cmbDept
此外,强烈建议您使用参数化查询以避免Little Bobby Tables的访问,如下所示:
Private Sub cmbCustomer_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmbCustomer.SelectedIndexChanged
sql = "SELECT * from Departments WHERE Customer = '" & cmbCustomer.Text & "'"
Dim cmd As New OleDb.OleDbCommand
cmd.CommandText = sql
cmd.Connection = oledbCnn
dr = cmd.ExecuteReader
If (dr.HasRows) Then
While dr.Read()
cmbDept.Text = CStr((dr("Name"))) <--- 2nd combobox
End While
End If
cmd.Dispose()
dr.Close()
End Sub