How do i handle a multiple null image values from Microsoft SQL Server database with vb.net code - vb.net

I was hoping someone could point me in the right direction with my current code. I'm getting an error while opening my program:
Data is Null. This method or property cannot be called on null values.
I put an else statement for btn.backgroundimage but still get that error.
Here is what my code looks like:
Sub FillItems()
Try
con = New SqlConnection(cs)
con.Open()
Dim PictureCol As Integer = 1 ' the column # of the BLOB field
Dim cmdText1 As String = "SELECT RTRIM(ProductName),Image from Temp_Stock_Company INNER JOIN Product ON Product.PID=Temp_Stock_Company.ProductID where ShowPOS='Yes'"
cmd = New SqlCommand(cmdText1)
cmd.Connection = con
cmd.CommandTimeout = 0
rdr = cmd.ExecuteReader()
flpItems.Controls.Clear()
Do While (rdr.Read())
'Dim btn As New Button
'btn.Text = rdr.GetValue(0)
'btn.TextAlign = ContentAlignment.MiddleCenter
'btn.BackColor = Color.SteelBlue
'btn.ForeColor = Color.White
'btn.FlatStyle = FlatStyle.Popup
'btn.Width = 125
'btn.Height = 60
'btn.Font = New System.Drawing.Font("Microsoft Sans Serif", 10.0!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
'UserButtons.Add(btn)
'flpItems.Controls.Add(btn)
Dim b(rdr.GetBytes(PictureCol, 0, Nothing, 0, Integer.MaxValue) - 1) As Byte
rdr.GetBytes(PictureCol, 0, b, 0, b.Length)
Dim ms As New System.IO.MemoryStream(b)
Dim Dflp As New FlowLayoutPanel
Dflp.Size = New System.Drawing.Size(197, 197)
Dflp.BackColor = Color.Black
Dflp.BorderStyle = BorderStyle.None
Dflp.FlowDirection = FlowDirection.TopDown
Dim btn As New Button
Dim btnX As New Button
btn.Text = rdr.GetValue(0)
btn.Width = 197
btn.Height = 197
If DBNull.Value.Equals(rdr(1)) = False Then
btn.BackgroundImage = Image.FromStream(ms)
btn.BackgroundImageLayout = ImageLayout.Stretch
Else
btn.BackgroundImage = My.Resources._12
btn.BackgroundImageLayout = ImageLayout.Stretch
End If
btn.FlatStyle = FlatStyle.Flat
btn.FlatAppearance.BorderSize = 0
btn.Text = rdr.GetValue(0)
btn.Font = New System.Drawing.Font("Segoe UI Semibold", 1.0!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
btn.TextAlign = System.Drawing.ContentAlignment.BottomCenter
btn.ForeColor = System.Drawing.Color.Black
btnX.Text = rdr.GetValue(0)
btnX.FlatStyle = FlatStyle.Flat
btnX.Width = 0
btnX.Height = 0
btnX.FlatAppearance.BorderSize = 0
btnX.Text = rdr.GetValue(0)
btnX.Font = New System.Drawing.Font("Segoe UI Semibold", 8.0!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
btnX.TextAlign = System.Drawing.ContentAlignment.MiddleCenter
btnX.ForeColor = Color.White
btnX.BackColor = Color.SteelBlue
UserButtons.Add(btn)
UserButtons.Add(btnX)
Dflp.Controls.Add(btn)
Dflp.Controls.Add(btnX)
flpItems.Controls.Add(Dflp)
AddHandler btn.Click, AddressOf Me.btnItems_Click
AddHandler btnX.Click, AddressOf Me.btnItems_Click
Loop
con.Close()
Catch ex As Exception
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.[Error])
End Try
End Sub

You do not want to hold the connection open while you update the user interface so I have used a DataTable which will hold your data after the connection is closed and disposed. Using...End Using blocks will close and dispose your database objects. Any class in the framework that shows you a .Dispose method should be enclosed in Using blocks. This includes streams.
Load the DataTable. Check for DBNull and only then get your byte array.
I used AdventureWorks (a sample database available from Microsoft) to test.
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim dt As New DataTable
Using cn As New SqlConnection(My.Settings.Adventure),
cmd As New SqlCommand("Select Top 10 ProductPhotoID, ThumbNailPhoto From Production.ProductPhoto;", cn)
cn.Open()
Using reader = cmd.ExecuteReader
dt.Load(reader)
End Using
End Using
For Each row As DataRow In dt.Rows
Dim btn As New Button
If Not IsDBNull(row(1)) Then
Dim b() As Byte = DirectCast(row(1), Byte())
Using ms As New System.IO.MemoryStream(b)
btn.BackgroundImage = Image.FromStream(ms)
End Using
Else
btn.BackgroundImage = Image.FromFile("C:\Users\***\Desktop\Graphics\TreeFrog.jpg")
End If
btn.BackgroundImageLayout = ImageLayout.Stretch
btn.Width = 50
btn.Height = 50
FlowLayoutPanel1.Controls.Add(btn)
Next
End Sub

Related

Search data from FlowLayoutPanel

How can I make my textbox.text when I enter something to fetch results in flowlayoutpanel and if i remove text form textbox to show all again.
Simply search option inside the flowpanel to show found records.
The code that create the flowlayoutpanel when form loads:
Private Sub GenerateDynamicUserControl()
FlowLayoutPanel1.Controls.Clear()
Dim dt As DataTable = New ClassBLL().GetItems()
If dt IsNot Nothing Then
If dt.Rows.Count > 0 Then
Dim listItems As ListItem() = New ListItem(dt.Rows.Count - 1) {}
For i As Integer = 0 To 1 - 1
For Each row As DataRow In dt.Rows
Dim listItem As New ListItem()
listItems(i) = listItem
'Dim ms As New MemoryStream(CType(row("userPic"), Byte()))
Dim ms As New MemoryStream(CType(row("UserPictureFrom"), Byte()))
Dim ms2 As New MemoryStream(CType(row("UserPictureTo"), Byte()))
listItems(i).Width = FlowLayoutPanel1.Width - 30
listItems(i).Icon = New Bitmap(ms)
listItems(i).Icon2 = New Bitmap(ms2)
listItems(i).OrderFrom = row("orderfrom").ToString()
listItems(i).OrderTitle = row("UserPositionFrom").ToString()
listItems(i).OrderReceiver = row("orderreceiver").ToString()
listItems(i).OrderTitle2 = row("UserPositionTo").ToString()
'listItems(i).ButtonBackground = orderButtonBackString
listItems(i).ButtonText = row("orderstatus").ToString()
listItems(i).OrderDate = row("orderdate")
listItems(i).IDOrder = row("orderid").ToString()
listItems(i).Subject = row("ordersubject").ToString()
listItems(i).SubjectText = row("ordersubjecttext").ToString()
If listItems(i).ButtonText = "Accepted" Then
listItems(i).ButtonBackground = Color.FromArgb(26, 168, 92)
ElseIf listItems(i).ButtonText = "Declined" Then
listItems(i).ButtonBackground = Color.FromArgb(246, 50, 90)
ElseIf listItems(i).ButtonText = "Proceed" Then
listItems(i).ButtonBackground = Color.FromArgb(255, 174, 33)
ElseIf listItems(i).ButtonText = "Waiting" Then
listItems(i).ButtonBackground = Color.FromArgb(53, 121, 255)
Else
listItems(i).ButtonBackground = Color.FromArgb(91, 146, 255)
End If
FlowLayoutPanel1.Controls.Add(listItems(i))
Next
Next
End If
End If
End Sub
The class:
Public Function ReadItemsTable() As DataTable
Using cons As New SQLiteConnection(ServerStatus)
Using cmd As New SQLiteCommand()
cmd.Connection = cons
'cmd.CommandText = "SELECT * FROM OrdersAssigned ORDER BY ID ASC"
cmd.CommandText = "SELECT OrdersAssigned.*,
ProfilesFrom.userPosition AS UserPositionFrom,
ProfilesFrom.userPicture AS UserPictureFrom,
ProfilesTo.userPosition AS UserPositionTo,
ProfilesTo.userPicture AS UserPictureTo
FROM
(OrdersAssigned
LEFT OUTER JOIN Profiles AS ProfilesFrom ON OrdersAssigned.orderacc = ProfilesFrom.userAccount)
LEFT OUTER JOIN Profiles AS ProfilesTo ON OrdersAssigned.orderreceiveracc = ProfilesTo.userAccount
ORDER BY
OrdersAssigned.ID ASC;"
cons.Open()
Using sda As New SQLiteDataAdapter(cmd)
Dim dt As New DataTable()
sda.Fill(dt)
Return dt
End Using
End Using
End Using
End Function
and on my button "btnSearchOrders_TextChanged" I need to input the search method any ideas how to do that without calling new query?
On the textbox TextChanged event try something like:
For Each myControl As Control In myflowlayoutcontrol.Controls
If myControl.text=mytextboxname.text then
'found it!
End if
'more code goes here
Next
the code inside the .TextChanged function will run every time the text of the textbox change and will search for the text on it in the flow control objects .text strings.
Let me know if you need more help.

Create Previous, Next Buttons in FlowLayoutPanel

can someone help me to add buttons for Previous Next and pages between them.
For example in my FlowLayoutPanel1 it display 4 results, because i do not want to use autoscroll=true
what i want to do is after the 4th results by pressing button to continue to next records display in the flowlayoutpanel and so one.
What i mean is to create outside the flowlayout buttons Previous,1,2,3,4,Next buttons that when click to do action inside the flowlayoutpanel
Demo Buttons
Something like that i would like to create
Here is my code for add stuff in the layoutpanel
Private Sub GenerateDynamicUserControl()
FlowLayoutPanel1.Controls.Clear()
Dim dt As DataTable = New ClassBLL().GetItems()
If dt IsNot Nothing Then
If dt.Rows.Count > 0 Then
Dim listItems As ListItem() = New ListItem(dt.Rows.Count - 1) {}
For i As Integer = 0 To 1 - 1
For Each row As DataRow In dt.Rows
Dim listItem As New ListItem()
listItems(i) = listItem
'Dim ms As New MemoryStream(CType(row("userPic"), Byte()))
listItems(i).Width = FlowLayoutPanel1.Width
listItems(i).Icon = orderPicFromString
listItems(i).Icon2 = orderPicFromString2
listItems(i).OrderFrom = row("orderacc").ToString()
listItems(i).OrderTitle = row("orderfrom").ToString()
listItems(i).OrderReceiver = row("orderreceiveracc").ToString()
listItems(i).OrderTitle2 = row("orderreceiver").ToString()
'listItems(i).ButtonBackground = orderButtonBackString
listItems(i).ButtonText = row("orderstatus").ToString()
listItems(i).OrderDate = row("orderdate")
listItems(i).IDOrder = row("orderid").ToString()
If listItems(i).ButtonText = "Accepted" Then
listItems(i).ButtonBackground = Color.FromArgb(26, 168, 92)
ElseIf listItems(i).ButtonText = "Declined" Then
listItems(i).ButtonBackground = Color.FromArgb(246, 50, 90)
ElseIf listItems(i).ButtonText = "Proceed" Then
listItems(i).ButtonBackground = Color.FromArgb(255, 174, 33)
ElseIf listItems(i).ButtonText = "Waiting" Then
listItems(i).ButtonBackground = Color.FromArgb(53, 121, 255)
Else
listItems(i).ButtonBackground = Color.FromArgb(91, 146, 255)
End If
FlowLayoutPanel1.Controls.Add(listItems(i))
Next
Next
End If
End If
End Sub
And the code that calls the read of database MS Access DB is like this:
Public Function ReadItemsTable() As DataTable
Using cons As New OleDbConnection(ServerStatus)
Using cmd As New OleDbCommand()
cmd.Connection = cons
cmd.CommandText = "SELECT * FROM OrdersAssigned ORDER BY ID ASC"
cons.Open()
Using sda As New OleDbDataAdapter(cmd)
Dim dt As New DataTable()
sda.Fill(dt)
Return dt
End Using
End Using
End Using
End Function
Public Function GetItems() As DataTable
Try
Dim objdal As New ClassDAL()
Return objdal.ReadItemsTable()
Catch e As Exception
Dim result As DialogResult = MessageBox.Show(e.Message.ToString())
Return Nothing
End Try
End Function

Read from two tables information

How can i convert this code to read information from the two tables.
Private Sub GenerateDynamicUserControl()
FlowLayoutPanel1.Controls.Clear()
Dim dt As DataTable = New ClassBLL().GetItems()
If dt IsNot Nothing Then
If dt.Rows.Count > 0 Then
Dim listItems As ListItem() = New ListItem(dt.Rows.Count - 1) {}
For i As Integer = 0 To 1 - 1
For Each row As DataRow In dt.Rows
Dim listItem As New ListItem()
listItems(i) = listItem
'Dim ms As New MemoryStream(CType(row("userPic"), Byte()))
listItems(i).Width = FlowLayoutPanel1.Width - 30
listItems(i).Icon = orderPicFromString
listItems(i).Icon2 = orderPicFromString2
listItems(i).OrderFrom = row("orderfrom").ToString()
listItems(i).OrderTitle = orderTitleString
listItems(i).OrderReceiver = row("orderreceiver").ToString()
listItems(i).OrderTitle2 = orderTitleString2
'listItems(i).ButtonBackground = orderButtonBackString
listItems(i).ButtonText = row("orderstatus").ToString()
listItems(i).OrderDate = row("orderdate")
listItems(i).IDOrder = row("orderid").ToString()
If listItems(i).ButtonText = "Accepted" Then
listItems(i).ButtonBackground = Color.FromArgb(26, 168, 92)
ElseIf listItems(i).ButtonText = "Declined" Then
listItems(i).ButtonBackground = Color.FromArgb(246, 50, 90)
ElseIf listItems(i).ButtonText = "Proceed" Then
listItems(i).ButtonBackground = Color.FromArgb(255, 174, 33)
ElseIf listItems(i).ButtonText = "Waiting" Then
listItems(i).ButtonBackground = Color.FromArgb(53, 121, 255)
Else
listItems(i).ButtonBackground = Color.FromArgb(91, 146, 255)
End If
FlowLayoutPanel1.Controls.Add(listItems(i))
Next
Next
End If
End If
End Sub
So let me start with information about this that is in RED , i need to get this information from another table that is called "Profiles"
listItems(i).Icon = orderPicFromString
listItems(i).Icon2 = orderPicFromString2
listItems(i).OrderTitle = orderTitleString
listItems(i).OrderTitle2 = orderTitleString2
So this fields i need to read them from table "Profiles"
So next is as you see the code up calls Class GetItems:
Public Function GetItems() As DataTable
Try
Dim objdal As New ClassDAL()
Return objdal.ReadItemsTable()
Catch e As Exception
Dim result As DialogResult = MessageBox.Show(e.Message.ToString())
Return Nothing
End Try
End Function
Public Function ReadItemsTable() As DataTable
Using cons As New OleDbConnection(ServerStatus)
Using cmd As New OleDbCommand()
cmd.Connection = cons
cmd.CommandText = "SELECT * FROM OrdersAssigned ORDER BY ID ASC"
cons.Open()
Using sda As New OleDbDataAdapter(cmd)
Dim dt As New DataTable()
sda.Fill(dt)
Return dt
End Using
End Using
End Using
End Function
So this is main function to display the results from row("name")
Then i try to create like this:
'Declare Strings for OrderDisplay
Public orderFromString As String
Public orderTitleString As String
Public orderReceiveString As String
Public orderTitleString2 As String
Public orderButtonBackString As Color
Public orderButtonTextString As String
Public orderDateString As Date
Public orderIDString As String
Public orderPicFromString As Image
Public orderPicFromString2 As Image
'Get Accounts Name
Public orderAccountFrom As String
Public orderAccountTo As String
Public Sub GetUserPictureFrom()
Using conn As New OleDbConnection(ServerStatus)
conn.Open()
Dim sql As String = "Select userPicture From Profiles where userAccount=#GetLogin"
Using cmd As New OleDbCommand(sql, conn)
cmd.Parameters.AddWithValue("#GetLogin", orderAccountFrom)
Dim imageData As Byte() = DirectCast(cmd.ExecuteScalar(), Byte())
If imageData IsNot Nothing Then
Using stream As New MemoryStream(imageData)
Dim backgroundImage As Image = Image.FromStream(stream)
orderPicFromString = backgroundImage
End Using
End If
End Using
End Using
End Sub
Public Sub GetUserPictureTo()
Using conn As New OleDbConnection(ServerStatus)
conn.Open()
Dim sql As String = "Select userPicture From Profiles where userAccount=#GetLogin"
Using cmd As New OleDbCommand(sql, conn)
cmd.Parameters.AddWithValue("#GetLogin", orderAccountTo)
Dim imageData As Byte() = DirectCast(cmd.ExecuteScalar(), Byte())
If imageData IsNot Nothing Then
Using stream As New MemoryStream(imageData)
Dim backgroundImage As Image = Image.FromStream(stream)
orderPicFromString2 = backgroundImage
End Using
End If
End Using
End Using
End Sub
Public Sub GetOrdersDisplay()
Using cons As New OleDbConnection(ServerStatus)
Using cmd As New OleDbCommand()
cmd.Connection = cons
cmd.CommandText = "SELECT * FROM OrdersAssigned ORDER BY ID ASC"
cons.Open()
Using rdr As OleDbDataReader = cmd.ExecuteReader()
While rdr.Read()
orderAccountFrom = rdr("orderacc").ToString
orderAccountTo = rdr("orderreceiveracc").ToString
End While
End Using
cmd.CommandText = "Select userPosition From Profiles where userAccount = #GetUser"
cmd.Parameters.Clear()
cmd.Parameters.AddWithValue("#GetUser", orderAccountFrom)
Using rds As OleDbDataReader = cmd.ExecuteReader()
While rds.Read()
orderTitleString = rds("userPosition").ToString
End While
End Using
cmd.CommandText = "Select userPosition From Profiles where userAccount = #ToUser"
cmd.Parameters.Clear()
cmd.Parameters.AddWithValue("#ToUser", orderAccountTo).ToString()
Using rdx As OleDbDataReader = cmd.ExecuteReader()
While rdx.Read()
orderTitleString2 = rdx("userPosition").ToString
End While
End Using
End Using
End Using
GetUserPictureFrom()
GetUserPictureTo()
End Sub
What it needs to do is:
orderAccountFrom = rdr("orderacc").ToString
orderAccountTo = rdr("orderreceiveracc").ToString
will get the accounts from table OrdersAssigned and search with them in table Profiles to get results userPosition
What means this
userx in Profiles has userPosition = Boss
usery in Profiles has userPosition = Worker
i want to fetch this information.
The same goes for the pictures each user has his own picture.
How can i manage to fix this issue so to get correct data?
How can i combine all of this inside the function ReadItemsTable() it would be better to be in one place everything so
listItems(i).Icon = orderPicFromString
listItems(i).Icon2 = orderPicFromString2
listItems(i).OrderTitle = orderTitleString
listItems(i).OrderTitle2 = orderTitleString2
to work correct to get information
cmd.CommandText = "SELECT OrdersAssigned.*,
ProfilesFrom.userPosition AS UserPositionFrom,
ProfilesFrom.userPicture AS UserPictureFrom,
ProfilesTo.userPosition AS UserPositionTo,
ProfilesTo.userPicture AS UserPictureTo
FROM
(OrdersAssigned
LEFT OUTER JOIN Profiles AS ProfilesFrom ON OrdersAssigned.orderacc = ProfilesFrom.userAccount)
LEFT OUTER JOIN Profiles AS ProfilesTo ON OrdersAssigned.orderreceiveracc = ProfilesTo.userAccount
ORDER BY
OrdersAssigned.ID ASC;"

Display image in Datagridview

I am trying to display image in datagridview using ms-access and vb.net 2012.
my database in store image path does not image directly so when try to retrieve image in datagridview it shows the image path, not the image.
so how can I fix it?
Private Sub design_list_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'Design_managementDataSet.design_details' table. You can move, or remove it, as needed.
'Me.Design_detailsTableAdapter.Fill(Me.Design_managementDataSet.design_details)
cnn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\Design Management\Database\design_management.accdb"
If Not cnn.State = ConnectionState.Open Then
cnn.Open()
End If
designDatagridShow()
End Sub
Private Sub designDatagridShow()
Dim ds As New DataSet
Dim dt As New DataTable
ds.Tables.Add(dt)
Dim da As New OleDbDataAdapter
da = New OleDbDataAdapter("select * from design_details", cnn)
da.Fill(dt)
design_datagridview.AutoGenerateColumns = False
Dim ColImage As New DataGridViewImageColumn
Dim Img As New DataGridViewImageCell
design_datagridview.ColumnCount = 3
design_datagridview.Columns(0).Name = "design_number"
design_datagridview.Columns(0).HeaderText = "Design Number"
design_datagridview.Columns(0).DataPropertyName = "design_number"
design_datagridview.Columns(1).Name = "design_collection"
design_datagridview.Columns(1).HeaderText = "Design Collection"
design_datagridview.Columns(1).DataPropertyName = "design_collection"
design_datagridview.Columns(2).Name = "price"
design_datagridview.Columns(2).HeaderText = "Design Price"
design_datagridview.Columns(2).DataPropertyName = "price"
design_datagridview.Columns(3).Name = "design_image"
design_datagridview.Columns(3).HeaderText = "Design Image"
design_datagridview.Columns(3).DataPropertyName = "design_image"
design_datagridview.DataSource = dt
Dim value As String
value = design_datagridview.Columns(3).HeaderText = "design_image"
Label1.Text = value
cnn.Close()
End Sub
Update 1:
Thanks.
Add another column that is of System.Drawing.Image datatype, then set the image based on your image column's path using System.Drawing.Image.FromFile(...) like the following:
Dim imageColumn As New DataColumn
imageColumn.ColumnName = "ActualImage"
imageColumn.DataType = GetType(System.Drawing.Image)
dt.Columns.Add(ImageColumn)
For Each row As DataRow in dt.Rows
row("ActualImage") = System.Drawing.Image.FromFile(row("design_image"))
Next
dt.AcceptChanges()
Dim dgvImageColumn As New DataGridViewImageColumn
dgvImageColumn.DataPropertyName = "ActualImage"
dgvImageColumn.Name = "ActualImage"
dgvImageColumn.ImageLayout = DataGridViewImageCellLayout.Zoom
design_datagridview.Columns.Add(dgvImageColumn)
design_datagridview.DataSource = dt

SQL Download Image into Picture Box 'Out of Memory' Error

*strong text*Okay, I've got a test application which is just to test the Uploading and Downloading of images to/from an SQL Server. The upload code works, but when I try to retrieve the image from the SQL Server I receive an 'Out of Memory' error. However, when I change the picturebox from .BackGroundImage to just .Image the code works flawlessly.
I require the image to be in the format of a BackGoundImage so that I can easily change the size of the image (center, stretch ect).
The error:
An unhandled exception of type 'System.OutOfMemoryException' occurred
in System.Drawing.dll
Additional information: Out of memory.
The code for retrieving the image from the SQL Server is:
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
'Retrieve Image
GroupBox2.BringToFront()
GroupBox2.Visible = True
Label1.Visible = False
TextBox1.Visible = False
con.Open()
Dim cmd As New SqlCommand("SELECT DP FROM PersonsA WHERE Members_ID = 1", con)
cmd.CommandType = CommandType.Text
Dim ImgStream As New IO.MemoryStream(CType(cmd.ExecuteScalar, Byte()))
PictureBox2.BackgroundImage = Image.FromStream(ImgStream, False, True)
ImgStream.Dispose()
con.Close()
End Sub
The error highlights the PictureBox2.BackgroundImage = Image.FromStream(ImgStream, False, True) line.
Additional information:
Only 1 row is expected as Members_ID is Primary Key.
SQL Server is MS SQL Server + Management Studio.
The DP Column is formatted as 'Image' and stores the picture like this:
0xFFD8FFE000104A46494600010201000000000000FF....
Here's the upload image code (WORKING)
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
'Upload Image
con.Open()
Dim cmd As New SqlCommand("UPDATE PersonsA SET DP=#DP WHERE Members_ID = 1", con)
Dim ms As New MemoryStream()
PictureBox1.BackgroundImage.Save(ms, PictureBox1.BackgroundImage.RawFormat)
Dim data As Byte() = ms.GetBuffer()
Dim p As New SqlParameter("#DP", SqlDbType.Image)
p.Value = data
cmd.Parameters.Add(p)
cmd.ExecuteNonQuery()
MessageBox.Show("Image has been saved", "Save", MessageBoxButtons.OK)
Label1.Visible = False
TextBox1.Visible = False
con.Close()
Imports and Dims
Imports System.Data.SqlClient
Imports System.IO
Public Class Form1
'path variable use for Get application running path
Dim path As String = (Microsoft.VisualBasic.Left(Application.StartupPath, Len(Application.StartupPath) - 9))
Dim con As New SqlConnection("CONNECTION_STRING;")
Dim cn As New SqlConnection("CONNECTION_STRING;")
Dim cmd As SqlCommand
Any ideas on why I'm receiving the 'Out of Memory Error'? The program is tiny and doesn't seam to be using excessive amounts of RAM so it has to be with my code...
[EDIT 1]
Following Jaques very helpful advice I've changed my code to the following - note there's two errors as read is not declared - what should that be declared as?
Dim cmd As New SqlCommand("SELECT DP FROM PersonsA WHERE Members_ID = 1", con)
cmd.CommandType = CommandType.Text
Dim Buffersize As Integer = 4096
Dim retval As Long = 0
Dim TempLen1 As Long = 0
Dim startindex As Long = 0
Dim reference_temp As [Byte]() = New [Byte](4095) {}
Dim RefTemp As New List(Of Byte)()
Dim Read As
retval = read.GetBytes(0, startindex, reference_temp, 0, buffersize)
'0 is the first Column
TempLen1 += retval
While retval = buffersize
RefTemp.AddRange(reference_temp)
startindex += buffersize
retval = read.GetBytes(0, startindex, reference_temp, 0, buffersize)
TempLen1 += retval
End While
RefTemp.AddRange(reference_temp)
Dim Reference_temp1 As Byte() = RefTemp.GetRange(0, CInt(TempLen1)).ToArray()
End Sub
[EDIT 2]
I'm now receiving an error on the retval - read.GetBytes(16, startindex.... line.
An unhandled exception of type 'System.InvalidOperationException'
occurred in Microsoft.VisualBasic.dll
Additional information: Invalid attempt to read when no data is
present.
My code so far:
'Retrieve Image
GroupBox2.BringToFront()
GroupBox2.Visible = True
Label1.Visible = False
TextBox1.Visible = False
con.Open()
Dim cmd As New SqlCommand("SELECT DP FROM PersonsA WHERE Members_ID = 1", con)
cmd.CommandType = CommandType.Text
Dim read = cmd.ExecuteReader
Dim Buffersize As Integer = 4096
Dim retval As Long = 0
Dim TempLen1 As Long = 0
Dim startindex As Long = 0
Dim reference_temp As [Byte]() = New [Byte](4095) {}
Dim RefTemp As New List(Of Byte)()
retval = read.GetBytes(16, startindex, reference_temp, 16, Buffersize)
'0 is the first Column
TempLen1 += retval
While retval = buffersize
RefTemp.AddRange(reference_temp)
startindex += buffersize
retval = read.GetBytes(16, startindex, reference_temp, 16, Buffersize)
TempLen1 += retval
End While
RefTemp.AddRange(reference_temp)
Dim Reference_temp1 As Byte() = RefTemp.GetRange(16, CInt(TempLen1)).ToArray()
Dim ImgStream As New IO.MemoryStream(Reference_temp1)
PictureBox2.BackgroundImage = Image.FromStream(ImgStream, False, True)
ImgStream.Dispose()
Why don't you use the GetBytes from a DataReader like (Its C#, but I'm sure you can convert it :))
'Retrieve Image
GroupBox2.BringToFront()
GroupBox2.Visible = True
Label1.Visible = False
TextBox1.Visible = False
con.Open()
Dim cmd As New SqlCommand("SELECT DP FROM PersonsA WHERE Members_ID = 1", con)
cmd.CommandType = CommandType.Text
Dim read = cmd.ExecuteReader();
if(read.HadRows) then
read.Read() 'Reads the first record from the DataReader
Convert this to VB:
int buffersize = 4096;
long retval = 0;
long TempLen1 = 0;
long startindex = 0;
Byte[] reference_temp = new Byte[4096];
List<byte> RefTemp = new List<byte>();
retval = read.GetBytes(0, startindex, reference_temp, 0, buffersize); //0 is the first Column
TempLen1 += retval;
while (retval == buffersize)
{
RefTemp.AddRange(reference_temp);
startindex += buffersize;
retval = read.GetBytes(0, startindex, reference_temp, 0, buffersize);
TempLen1 += retval;
}
RefTemp.AddRange(reference_temp);
byte[] Reference_temp1 = RefTemp.GetRange(0, (int)TempLen1).ToArray();
Then add your code
Dim ImgStream As New IO.MemoryStream(Reference_temp1)
PictureBox2.BackgroundImage = Image.FromStream(ImgStream, False, True)
ImgStream.Dispose()
EndIf
I'd like to thank Jaques for his/her efforts in helping me. The solution was a little simpler than that answer - which still resulted in a 'Out of Memory' Error. But the efforts made are extremely appreciated. In the end this code worked without any errors.
'Retrieve Image
GroupBox2.BringToFront()
GroupBox2.Visible = True
Label1.Visible = False
TextBox1.Visible = False
Dim stream As New MemoryStream()
con.Open()
Dim cmd As New SqlCommand("SELECT DP FROM PersonsA WHERE Members_ID = 1", con)
cmd.CommandType = CommandType.Text
Dim image As Byte() = DirectCast(cmd.ExecuteScalar(), Byte())
Stream.Write(image, 0, image.Length)
con.Close()
Dim bitmap As New Bitmap(stream)
PictureBox2.BackgroundImage = bitmap
PictureBox2.BackgroundImageLayout = ImageLayout.Stretch