繁体   English   中英

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

[英]How to retrieve image from database using ComboBox in VB.NET

我尝试通过它检索图像时遇到有关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

在大多数情况下,当您不关心各个部分或为用户创建一些新内容时,可以使用CONCAT字段。 例如将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

笔记:

我不熟悉您的应用程序和数据库的所有复杂性和详细信息,因此可能需要修复和修改某些内容。 正在说明其中涉及的原理。

由于职位的文字现在至关重要,因此您可能希望使用“常量”或名称数组来防止输入错误。 例如:

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等使用完全相同的文本,而在此处不要使用“ Vice President”,而在别处使用“ Vice-President”。

通过不将所有内容粘合在一起,您的原始问题可能会过时。 如果用于创建表的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注入攻击的保护的情况要少得多。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM