【问题标题】:How to execute two separate queries from one DBCommand object?如何从一个 DBCommand 对象执行两个单独的查询?
【发布时间】:2016-05-21 04:40:40
【问题描述】:

我有以下代码尝试从两个不同的表中获取记录,然后将它们添加到特定的组合框中。只有第一个查询有效,第二个被忽略。

    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

我可以想到另一种方法是在多个查询中执行此操作,但代码可以简化为这样的吗?

【问题讨论】:

    标签: mysql .net vb.net mysqldatareader


    【解决方案1】:

    使用带有 2 个查询的 DBDataReader,只执行第一个查询,因为无法指示每个读取项来自哪个表/查询。您的“双重读取”循环似乎假设它们将同时返回(而不是一个又一个查询 - 与它们发送到 DBCOMmand 的方式相同);如果它确实以这种方式工作,那么只要每个表中的行数不同,它就会失败。

    使用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)
    

    如果我查看输出窗口,它将打印2(表格)、10000(T(0) 中的行)和6(T(1) 中的行)。并非所有 DBProvider 都具有此功能。例如,访问将阻塞 SQL 字符串。对代码组成方式的其他更改:

    • DBConnections 和 DBCommand 对象需要被释放。它们分配资源,因此需要创建、使用和处置它们以释放这些资源。
    • Using 块为我们做到了这一点:目标对象在开始时创建,然后在 End Using 处关闭和处置。
    • 上面的代码堆叠或组合了 2 个这样的块。

    代码从查询中填充DataSet,在本例中创建了 2 个表。您可以使用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"
    

    结果将是每个表中出现在相应组合控件中的所有行。通常使用这种类型的东西,您需要 ID/PK 和对查询中的用户有意义的名称。用户会看到友好名称 (DisplayMember),代码可以轻松访问该名称的唯一标识符以进行选择 (ValueMember)。

    当使用绑定列表控件时,而不是使用SelectedIndexSelectedIndexChanged 事件,您应该使用SelectedValueSelectedItem 来访问实际数据。

    MSDN:Using Statement (Visual Basic)

    【讨论】:

    • 非常感谢您的清晰解释。但是我可以了解更多关于Using 的信息吗?这是否意味着我在使用Using 时不需要关闭连接?
    • Using 关闭并处理它。一般来说,任何具有Dispose 方法的东西都应该包含在Using 块中。
    【解决方案2】:

    您可以使用.net 连接器(下载here
    然后您可以安装它并将其添加到您的项目中(项目 -> 参考 -> 添加 -> 浏览)。
    最后添加导入:

    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 将包含两个数据表:每个查询一个

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多