如何从一个 DBCommand 对象执行两个单独的查询?
How to execute two separate queries from one DBCommand object?
我有以下代码尝试从两个不同的表中获取记录,然后将它们添加到特定的组合框中。只有第一个查询有效,第二个被忽略。
Try
sqlConn = New MySqlConnection
connStr = New String("Server = localhost; Database = gen_database; Uid = root; Pwd =")
sqlConn.ConnectionString = connStr
myCommand = New MySqlCommand("Select DevCompanyName from developer_name_table; Select DevType from development_type_table")
myCommand.CommandType = CommandType.Text
myCommand.Connection = sqlConn
ComboBox1.Items.Clear()
sqlConn.Open()
MsgBox("Connection Open.")
dR = myCommand.ExecuteReader()
Do While dR.Read()
ComboBox1.Items.Add(dR("DevCompanyName"))
ComboBox2.Items.Add(dR("DevType")) 'Error shows here Could not find specified column in results: DevType
Loop
Catch ex As MySqlException
MsgBox(ex.ToString)
Finally
dR.Close()
sqlConn.Close()
End Try
我可以想到另一种方法,即在多个查询中进行,但是代码可以简化为这样吗?
您可以使用 .net 连接器(下载 here)
然后你可以安装它并将它添加到你的项目中(项目 -> 引用 -> 添加 -> 浏览)。
最后添加 import:
Imports MySql.Data.MySqlClient
所以你将能够使用这个:
Dim connStr as String = "Server = localhost; Database = gen_database; Uid = root; Pwd ="
Dim SqlStr as String = "Select DevCompanyName from developer_name_table; Select DevType from development_type_table"
Dim ds As DataSet = MySqlHelper.ExecuteDataset(CnStr, SqlStr)
ds 将包含两个数据表:每个查询一个
使用带有 2 个查询的 DBDataReader
,只有第一个执行,因为没有办法表明每个读取的项目来自哪个 table/query。您的 "double read" 循环似乎假定它们将同时返回(而不是一个接一个地返回-与将它们发送到 DBCOmmand 的方式相同);如果它 did 那样工作,只要每个 table.
中的行数不同,它就会失败
使用 DataTables
让您有机会简单地将结果绑定到您的组合,而不是将数据复制到它们中:
Dim SQL = "SELECT * FROM Sample; SELECT * FROM Simple"
Dim ds As New DataSet
Using dbcon As New MySqlConnection(MySQLConnStr),
cmd As New MySqlCommand(SQL, dbcon)
dbcon.Open()
Dim da As New MySqlDataAdapter(cmd)
da.Fill(ds)
End Using
' debug results
Console.WriteLine(ds.Tables.Count)
Console.WriteLine(ds.Tables(0).Rows.Count)
Console.WriteLine(ds.Tables(1).Rows.Count)
如果我查看输出 window,它将打印 2
(tables)、10000
(T(0) 中的行)和 6
(T(1) 中的行)。并非所有 DBProvider 都具有此功能。例如,访问将在 SQL 字符串上阻塞。代码编写方式的其他更改:
- 需要释放 DBConnections 和 DBCommand 对象。它们分配资源,因此需要创建、使用和处置它们以释放这些资源。
Using
块为我们做了这些:目标对象在开始时创建,并在 End Using
时关闭和释放。
- 上面的代码堆叠或组合了 2 个这样的块。
代码从查询中填充 DataSet
,在本例中创建 2 table。与其将数据从一个容器复制到另一个容器(如控件),不如使用 DataTable
作为 DataSource
:
cboDevName.DataSource = ds.Tables(0)
cboDevName.DisplayMember = "DevName" ' column names
cboDevName.ValueMember = "Id"
cboDevType.DataSource = ds.Tables(1)
cboDevType.DisplayMember = "DevType"
cboDevType.ValueMember = "DevCode"
结果将是每个 table 中的所有行出现在各自的组合控件中。通常对于这种类型的东西,您需要 ID/PK 和对查询中的用户有意义的名称。用户看到友好名称 (DisplayMember
),代码可以轻松访问该选择的唯一标识符 (ValueMember
)。
当使用绑定列表控件时,而不是使用 SelectedIndex
和 SelectedIndexChanged
事件,您将使用 SelectedValue
和 SelectedItem
来访问实际数据。
我有以下代码尝试从两个不同的表中获取记录,然后将它们添加到特定的组合框中。只有第一个查询有效,第二个被忽略。
Try
sqlConn = New MySqlConnection
connStr = New String("Server = localhost; Database = gen_database; Uid = root; Pwd =")
sqlConn.ConnectionString = connStr
myCommand = New MySqlCommand("Select DevCompanyName from developer_name_table; Select DevType from development_type_table")
myCommand.CommandType = CommandType.Text
myCommand.Connection = sqlConn
ComboBox1.Items.Clear()
sqlConn.Open()
MsgBox("Connection Open.")
dR = myCommand.ExecuteReader()
Do While dR.Read()
ComboBox1.Items.Add(dR("DevCompanyName"))
ComboBox2.Items.Add(dR("DevType")) 'Error shows here Could not find specified column in results: DevType
Loop
Catch ex As MySqlException
MsgBox(ex.ToString)
Finally
dR.Close()
sqlConn.Close()
End Try
我可以想到另一种方法,即在多个查询中进行,但是代码可以简化为这样吗?
您可以使用 .net 连接器(下载 here)
然后你可以安装它并将它添加到你的项目中(项目 -> 引用 -> 添加 -> 浏览)。
最后添加 import:
Imports MySql.Data.MySqlClient
所以你将能够使用这个:
Dim connStr as String = "Server = localhost; Database = gen_database; Uid = root; Pwd ="
Dim SqlStr as String = "Select DevCompanyName from developer_name_table; Select DevType from development_type_table"
Dim ds As DataSet = MySqlHelper.ExecuteDataset(CnStr, SqlStr)
ds 将包含两个数据表:每个查询一个
使用带有 2 个查询的 DBDataReader
,只有第一个执行,因为没有办法表明每个读取的项目来自哪个 table/query。您的 "double read" 循环似乎假定它们将同时返回(而不是一个接一个地返回-与将它们发送到 DBCOmmand 的方式相同);如果它 did 那样工作,只要每个 table.
使用 DataTables
让您有机会简单地将结果绑定到您的组合,而不是将数据复制到它们中:
Dim SQL = "SELECT * FROM Sample; SELECT * FROM Simple"
Dim ds As New DataSet
Using dbcon As New MySqlConnection(MySQLConnStr),
cmd As New MySqlCommand(SQL, dbcon)
dbcon.Open()
Dim da As New MySqlDataAdapter(cmd)
da.Fill(ds)
End Using
' debug results
Console.WriteLine(ds.Tables.Count)
Console.WriteLine(ds.Tables(0).Rows.Count)
Console.WriteLine(ds.Tables(1).Rows.Count)
如果我查看输出 window,它将打印 2
(tables)、10000
(T(0) 中的行)和 6
(T(1) 中的行)。并非所有 DBProvider 都具有此功能。例如,访问将在 SQL 字符串上阻塞。代码编写方式的其他更改:
- 需要释放 DBConnections 和 DBCommand 对象。它们分配资源,因此需要创建、使用和处置它们以释放这些资源。
Using
块为我们做了这些:目标对象在开始时创建,并在End Using
时关闭和释放。- 上面的代码堆叠或组合了 2 个这样的块。
代码从查询中填充 DataSet
,在本例中创建 2 table。与其将数据从一个容器复制到另一个容器(如控件),不如使用 DataTable
作为 DataSource
:
cboDevName.DataSource = ds.Tables(0)
cboDevName.DisplayMember = "DevName" ' column names
cboDevName.ValueMember = "Id"
cboDevType.DataSource = ds.Tables(1)
cboDevType.DisplayMember = "DevType"
cboDevType.ValueMember = "DevCode"
结果将是每个 table 中的所有行出现在各自的组合控件中。通常对于这种类型的东西,您需要 ID/PK 和对查询中的用户有意义的名称。用户看到友好名称 (DisplayMember
),代码可以轻松访问该选择的唯一标识符 (ValueMember
)。
当使用绑定列表控件时,而不是使用 SelectedIndex
和 SelectedIndexChanged
事件,您将使用 SelectedValue
和 SelectedItem
来访问实际数据。