Store Images In SQL Server Using VB.Net and OleDB

I've wasted most of my day trying to get my VB.Net program to store pictures in a SQL Server database and have finally got it working. Most of the information and examples on the Internet refer to ASP.net or C# or are not using OleDB. And as usual, I had to wade through all the infuriating spam pages to find the info I needed. So here it is.

1) Add Image Field

First, add your field to your table with the Management Studio, or use a statement something like this:

ALTER TABLE myTable ADD myPicture image;

I also had this working using VarBinary(Max) as the data type. I'm not sure what the difference is, whether both types are available in different versions of SQL Server, or why you'd use one over the other.

2) Load Image Into PictureBox

Load an image into a PictureBox on the screen, so we can see what we're working with. Obviously you don't need to do this as two stages but it might help you to get it working. I am also scaling and resizing at this stage to ensure the pictures are nice and small as we're storing the images directly in the database (not included here).

Private Sub btnSetPic_Click(ByVal sender As System.Object, _
	ByVal e As System.EventArgs) Handles btnSetPic.Click

	Dim dlg As OpenFileDialog
	Dim img As Image

	Try
		dlg = New OpenFileDialog
		dlg.Filter = "All Pictures|*.bmp;*.gif;*.jpg;*.png|" & _
			"Bitmaps|*.bmp|GIFs|*.gif|JPEGs|*.jpg|PNGs|*.png"

		If dlg.ShowDialog = DialogResult.OK Then

			Me.Cursor = Cursors.WaitCursor
			PictureBox.Image = New Bitmap(dlg.FileName)

		End If

	Catch ex As Exception
		' My error handler
		m_errors.handle(ex)

	Finally
		img = Nothing
		dlg = Nothing

		Me.Cursor = Cursors.Default

	End Try

End Sub
		

3) Save the image from the PictureBox into the database

sKey is the primary key of the row that we want to contain the picture. myImage is the image we want to store. So call the function like: savePicture("FRED", PictureBox.Image)

    Private Sub savePicture(ByVal sKey As String, ByVal myImage As Image)

        Dim sql As String
        Dim da As OleDb.OleDbDataAdapter
        Dim cm As OleDb.OleDbCommand
        Dim cb As OleDb.OleDbCommandBuilder
        Dim dt As New DataTable
        Dim mstr As System.io.MemoryStream
        Dim arrImage() As Byte

        Try
            sql = _
                "SELECT rowId, myPicture " & _
                "FROM myTable " & _
                "WHERE rowId = '" & Replace(sKey, "'", "''") & "';"

            cm = New OleDb.OleDbCommand(sql, m_dbConnection)

            da = New OleDb.OleDbDataAdapter(cm)
            da.Fill(dt)

            If dt.Rows.Count = 0 Then
                Throw New CWarningException("Row " & sKey & " not found")
            End If

            If myImage Is Nothing Then
                dt.Rows(0)("myPicture") = DBNull.Value
            Else
                mstr = New System.io.MemoryStream
                myImage.Save(mstr, System.Drawing.Imaging.ImageFormat.Jpeg)
                arrImage = mstr.GetBuffer
                dt.Rows(0)("myPicture") = arrImage
            End If

            cb = New OleDb.OleDbCommandBuilder(da)

            da.Update(dt)

        Catch ex As Exception
            Throw

        Finally
            arrImage = Nothing
            mstr = Nothing
            dt = Nothing
            cb = Nothing
            cm = Nothing
            da = Nothing

        End Try

    End Sub
		

4) Retrieve the picture

Load the image data from the database and read into an Image data type.

First, get the DataTable containing the Row with the Image data we want to load into a DataTable called dt. Then use something like the following:

        Dim myImage As Image
        Dim barr() As Byte
        Dim imgstr As System.io.MemoryStream

        If IsDBNull(dr("myPicture")) Then
            ' No picture stored
            myImage = Nothing
        Else
            barr = CType(dr("myPicture"), Byte())

            If barr.GetUpperBound(0) > 0 Then
                imgstr = New System.io.MemoryStream(barr)

                myImage = Image.FromStream(imgstr)
            Else
                myImage = Nothing
            End If
        End If
		

You can then set myImage into your PictureBox or whatever.

Hopefully that should put you on the right track. I'm sure you'll have to fiddle about with this code a bit to get it working, but the method works. Wish I'd found a page like this this morning!

Page Updated 15/09/09