如何使用VB.NET中的ComboBox从数据库中检索图像

时间:2014-10-15 11:33:24

标签: mysql vb.net combobox

当我尝试通过它检索图像时,我对ComboBox的事件有疑问。因为当我使用这个时:

Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged

        Dim connstring As String = "server = localhost; user id = root; database = db; password = root"
        Dim Sql As String = "SELECT * FROM candidate WHERE cid= '" & ComboBox1.SelectedItem & "'"
        Dim conn As New MySqlConnection(connstring)
        Dim cmd As New MySqlCommand(Sql, conn)
        Dim dr As MySqlDataReader = Nothing
        conn.Open()
        dr = cmd.ExecuteReader()
        dr.Read()
        If IsDBNull(dr("photo")) = False Then
            Dim imagebytes As Byte() = CType(dr("photo"), Byte())
            Using ms As New IO.MemoryStream(imagebytes)
                PictureBox1.Image = Image.FromStream(ms)
                PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage
            End Using
        End If
        conn.Close()
End Sub

发生此错误:Operator '&' is not defined for string "SELECT * FROM candidate WHERE ci" and type 'DataRowView'.

但如果我使用这个:

Private Sub ComboBox1_SelectionChangeCommitted(ByVal sender As Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectionChangeCommitted

    Dim connstring As String = "server = localhost; user id = root; database = db; password = root"
    Dim Sql As String = "SELECT * FROM candidate WHERE cid= '" & ComboBox1.SelectedIndex & "'"
    Dim conn As New MySqlConnection(connstring)
    Dim cmd As New MySqlCommand(Sql, conn)
    Dim dr As MySqlDataReader = Nothing
    conn.Open()
    dr = cmd.ExecuteReader()
    dr.Read()
    If IsDBNull(dr("photo")) = False Then
        Dim imagebytes As Byte() = CType(dr("photo"), Byte())
        Using ms As New IO.MemoryStream(imagebytes)
            PictureBox1.Image = Image.FromStream(ms)
            PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage
        End Using
    End If
    conn.Close()
End Sub

首次选择正在运行,但是当我在ComboBox中选择另一个项目时,表单挂起(无响应)。我的代码或笔记本电脑有什么问题吗?

这就是我填充ComboBox es的方式:

Private Sub Form4_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    HookKeyboard()
    Me.TopMost = True
    con.ConnectionString = ("server=localhost;user id=root;database=db;password=root")
    Try
        con.Open()

        With cmd
            .Connection = con
            .CommandText = "SELECT case when SCQ='0' or cfname='Select a Candidate' then cfname else CONCAT_WS(' ', idn, cfname, cmname, clname,'from', cparty,'party') end names, " & _
            "cpos, cid from candidate WHERE cpos='President' AND candidacy='Filed' OR " & _
                       "cpos='Vice President' AND candidacy='Filed' OR " & _
                       "cpos='Secretary' OR " & _
                       "cpos='Treasurer' OR " & _
                       "cpos='Auditor' OR " & _
                       "cpos='Public Information Officer' OR " & _
                       "cpos='Peace Officer' OR " & _
                       "cpos='Representative (Grade 7)' order by SCQ desc "
        End With
        Dim dt As New DataTable

        da.SelectCommand = cmd
        da.Fill(dt)
        With ComboBox1
            Dim dv = New DataView(dt, "cpos='President'", "", DataViewRowState.CurrentRows)
            .DisplayMember = "names"
            .ValueMember = "names"
            .DataSource = dv
        End With
        With ComboBox2
            Dim dv1 = New DataView(dt, "cpos='Vice President'", "", DataViewRowState.CurrentRows)
            .DisplayMember = "names"
            .ValueMember = "names"
            .DataSource = dv1
        End With
        With ComboBox3
            Dim dv2 = New DataView(dt, "cpos='Secretary'", "", DataViewRowState.CurrentRows)
            .DisplayMember = "names"
            .ValueMember = "names"
            .DataSource = dv2
        End With
        With ComboBox4
            Dim dv3 = New DataView(dt, "cpos='Treasurer'", "", DataViewRowState.CurrentRows)
            .DisplayMember = "names"
            .ValueMember = "names"
            .DataSource = dv3
        End With
        With ComboBox5
            Dim dv4 = New DataView(dt, "cpos='Auditor'", "", DataViewRowState.CurrentRows)
            .DisplayMember = "names"
            .ValueMember = "names"
            .DataSource = dv4
        End With
        With ComboBox6
            Dim dv5 = New DataView(dt, "cpos='Public Information Officer'", "", DataViewRowState.CurrentRows)
            .DisplayMember = "names"
            .ValueMember = "names"
            .DataSource = dv5
        End With
        With ComboBox7
            Dim dv6 = New DataView(dt, "cpos='Peace Officer'", "", DataViewRowState.CurrentRows)
            .DisplayMember = "names"
            .ValueMember = "names"
            .DataSource = dv6
        End With
        With ComboBox8
            Dim dv7 = New DataView(dt, "cpos='Representative (Grade 7)'", "", DataViewRowState.CurrentRows)
            .DisplayMember = "names"
            .ValueMember = "names"
            .DataSource = dv7
        End With
    Catch ex As Exception
        MsgBox(ex.Message)
    End Try
    con.Close()
End Sub

1 个答案:

答案 0 :(得分:0)

在大多数情况下,当您不关心这些碎片或为用户创造新的东西时,您会使用CONCAT字段。例如,将FirstName和LastName连接成FullName。这不是真的,你想得到一些信息。您可以使用过程简化查询,以获取每个位置的数据(即具有7或8个表的数据集 - 每个位置一个)。

Public Class FormX

    Private myDS As DataSet          ' our data set for the results

    Private Form_Load(....
         myDS = New DataSet

         FillPositionInfo("President")
         FillPositionInfo("Vice-President")
         ...etc

         ' bind to CBOs:
        With ComboBox1
            .DisplayMember = "FullName"      ' what to show
            .ValueMember = "cid"             ' value to return to code
            .DataSource = myDS.Tables("President")
        End With

' add a table to the DS with the candidate info for the requested position
Private Sub FillPositionInfo(position As String)

    ' maybe CONCAT to create a full name field
    Dim sql As String = "SELECT cid, ... FROM Candidate WHERE cpos = @cpos"

    ' youd use MySql Objects - I only have SQL Server and Access available
    Using con As OleDbConnection = GetConnection()
        con.Open()
        Using cmd As New OleDbCommand(sql, con),
            da As New OleDbDataAdapter(sql.Value, con)

            cmd.Parameters.AddWithValue("@cpos", position)
            da.SelectCommand = cmd

            ' add a new Tbl named "President" or whatever is requested
            myDS.Tables.Add(position)            
            da.Fill(myDS, position)            ' fill the table
           ' debug - look in the output window
            For n As Integer = 0 To myDS.Tables(position).Rows.Count - 1
                Console.WriteLine(myDS.Tables(position).Rows(n).Item("cname")
            Next
        End Using            ' dispose cmd and da
        con.Close            ' return connection to pool
    End Using                ' dispose con
End Sub

注意:

我不熟悉您的应用和数据库的所有复杂性和细节,因此可能需要修复和修改。这是所涉及的原则,正在进行说明。

由于职位的文本现在至关重要,您可能希望使用常量或名称数组来防止拼写错误。 E.g:

Private posTitles As String() = {"President", "Vice President"...}
Private Enum TitleIndex
    President = 0
    VP = 1
    ...
End Enum
...
myDS.Tables.Add(posTitles(TitleIndex.VP))     ' add named tbl using array text
CBO.DataSource = myDS.Tables(TitleIndex.VP)  ' reference by position

关键是你要确保对DS表,CBO,SQL等使用相同的确切文本,而不是在这里使用“副总裁”,在其他地方使用“副总统”。

通过不将所有内容粘在一起,您的原始问题可能会被废弃。如果用于创建表的SQL是最小的(“SELECT Fname,LName,CID From ...”),那么您将需要再次点击DB以获得更多信息,如照片:

' assumes cid is the PK and mapped as the ValueMember
Sql = "SELECT * FROM candidate WHERE cid = '" & ComboBox1.SelectedValue & "'"

(如果cid是数字,则您不需要或不需要刻度 - 可能是数据类型转换。)

如果你使用“SELECT *”,那么每个DataTable已经包含了所有信息,无需查看任何内容。所选候选项的字节数组如下:

myDS.Tables(X).Rows(Cbo.SelectedIndex).Item("photo")` 

您仍然需要将其转换为实际图片,但无需找到它。有几种方法可以解决这个问题 - 所以你可能想修补它,如果这就是你的方法。

最后,请注意,使用SQL参数是一种很多更好的做法,如FillPositionInfo所示。字符串格式中的错误,数据类型不匹配以及对SQL注入攻击的保护要少得多。