Check if image column is Null VB.NET - vb.net

Good Day everyone. I need help with my code below.
Dim stream As New MemoryStream()
connect()
Dim command As New SqlCommand("SELECT image FROM tblHouseholdMembers WHERE id= '" & lvmem.FocusedItem.Text & "'", cn)
Dim image As Byte() = DirectCast(command.ExecuteScalar(), Byte()) --> 'Error message of null image
stream.Write(image, 0, image.Length)
cn.Close()
Dim bitmap As New Bitmap(stream)
pbProfilePic.Image = bitmap
I want to put a messagebox to identify if it's null before the error cast.

Instead of using the DirectCast method, use the TryCast and then check if the casting result is nothing:
Dim image As Byte() = TryCast(command.ExecuteScalar(), Byte())
if image isnot nothing then
stream.Write(image, 0, image.Length)
cn.Close()
Dim bitmap As New Bitmap(stream)
pbProfilePic.Image = bitmap
else
'Error message here
end if

The way to directly test if a field coming back from a database is null is:
if ValueFromDb is System.DbNull.Value then
' whatever you want to do in that case
Something that really confused me when I was first learning VB is that a null value from a DB read is NOT equal to Nothing. It is not Nothing, it is System.DbNull.Value.
Most of my projects these days, I write a little function I call "denull" that says something like:
public shared function denull(value as object, defalt as object)
if value is system.dbnull.value then
return defalt
else
return value
end function
Then I wrap every value I read from the db in this function. This saves a lot of code.
for each row in mydataset.tables(0).rows
foo=denull(row("foo"),"")
bar=denull(row("bar"),0)
plugh=denull(row("plugh"),nothing)
... etc ...

Related

Show image in vb.net

I'm trying to show a saved image in SQL Server but it gives me an error that says "parameter is not valid".
While oDataReader.Read()
TextBox1.Text = oDataReader("nombre")
Dim imagenbyte As Byte()
imagenbyte = oDataReader("imagen")
Dim mStream As New IO.MemoryStream()
mStream.Write(imagenbyte, 0, Convert.ToInt32(imagenbyte.Length))
Dim bm As Bitmap = New Bitmap(mStream, True)
PictureBox1.Image = bm
End While
You can consolidate that code down to this:
While oDataReader.Read()
TextBox1.Text = oDataReader("nombre")
Dim mStream As New IO.MemoryStream(oDataReader("imagen"))
PictureBox1.Image = Image.FromStream(mStream)
End While
The main fix here is using Image instead of Bitmap. And if you know you'll only have one record, you should change While to If. If you might have more than one record, you need to completely re-think some things in your user interface.

SqlFileStream writing in separate thread not working

Learning and testing using Sql FILESTREAM for a web app. A client uploads a large file form the web page which takes 'X' time and when fully uploaded shows 100% complete. However, very large files also take time for SqlFileStream to write to the file system so I want to spin off a thread to complete that part. The code I've got seems to work fine but no data ends up in the filestream file.
I'm wrapping the initial record creation in it's own transaction scope and using a separate transaction scope in the thread. In the threaded routine I have the appropriate PathName() and TransactionContext but I assume I'm missing something while using a thread.
I've commented out the normal SqlFileStream call which works fine. Can you see anything wrong with what I'm doing here?
Public Function StoreFileStream()
Dim json As New Dictionary(Of String, Object)
Dim parms As New FileStreamThreadParameters
If HttpContext.Current.Request.Files.Count > 0 Then
Dim file As HttpPostedFile = HttpContext.Current.Request.Files(0)
If "contentType" <> String.Empty Then
Dim fs As Stream = file.InputStream
Dim br As New BinaryReader(fs)
Dim noBytes As New Byte()
Try
Dim filePath As String = ""
Dim trxContext As Byte() = {}
Dim baseFileId As Integer
Using trxScope As New TransactionScope
Using dbConn As New SqlConnection(DigsConnStr)
Using dbCmd As New SqlCommand("ADD_FileStreamFile", dbConn)
dbConn.Open()
Using dbRdr As SqlDataReader = dbCmd.ExecuteReader(CommandBehavior.SingleRow)
dbRdr.Read()
If dbRdr.HasRows Then
filePath = dbRdr("Path")
trxContext = dbRdr("TrxContext")
baseFileId = dbRdr("BaseFileID")
End If
dbRdr.Close()
End Using
' Code below writes to file, but trying to offload this to a separate thread so user is not waiting
'Using dest As New SqlFileStream(filePath, trxContext, FileAccess.Write)
' fs.CopyTo(dest, 4096)
' dest.Close()
'End Using
End Using
dbConn.Close()
End Using
trxScope.Complete()
End Using ' transaction commits here, not in line above
parms.baseFileId = baseFileId
parms.fs = New MemoryStream
fs.CopyTo(parms.fs)
Dim fileUpdateThread As New Threading.Thread(Sub()
UpdateFileStreamThreaded(parms)
End Sub)
fileUpdateThread.Start()
json.Add("status", "success")
Catch ex As Exception
Elmah.ErrorSignal.FromCurrentContext().Raise(ex)
json.Add("status", "failure")
json.Add("msg", ex.Message)
json.Add("procedure", System.Reflection.MethodBase.GetCurrentMethod.Name)
End Try
Else
json.Add("status", "failure")
json.Add("msg", "Invalid file type")
json.Add("procedure", System.Reflection.MethodBase.GetCurrentMethod.Name)
End If
End If
Return json
End Function
Public Class FileStreamThreadParameters
Public Property baseFileId As Integer
Public fs As Stream
End Class
Private Sub UpdateFileStreamThreaded(parms As FileStreamThreadParameters)
Dim filePath As String = ""
Dim trxContext As Byte() = {}
Try
Using trxScope As New TransactionScope
Using dbConn As New SqlConnection(DigsConnStr)
Using dbCmd As New SqlCommand("SELECT FileBytes.PathName() 'Path', GET_FILESTREAM_TRANSACTION_CONTEXT() 'TrxContext' FROM FileStreamFile WHERE Id = " & parms.baseFileId, dbConn)
dbConn.Open()
Using dbRdr As SqlDataReader = dbCmd.ExecuteReader(CommandBehavior.SingleRow)
dbRdr.Read()
If dbRdr.HasRows Then
filePath = dbRdr("Path")
trxContext = dbRdr("TrxContext")
End If
dbRdr.Close()
Using dest As New SqlFileStream(filePath, trxContext, FileAccess.Write)
parms.fs.CopyTo(dest, 4096)
dest.Close()
End Using
End Using
End Using
dbConn.Close()
End Using
trxScope.Complete()
End Using
Catch ex As Exception
'Elmah.ErrorSignal.FromCurrentContext().Raise(ex)
End Try
End Sub
Obviously this is a complex issue. I actually got it to work with the code below. However I eventually abandoned using SQL FILESTREAM altogether due to too much complexity in getting it all set up.
This is an existing web application with the sql server on a different box. After I got the filestreaming to work the next hurdle was authentication setup. Filestream requires Integrated Security on your connection string. Even with windows authentication on our Intranet app, I could not get the web app to use the windows credentials when connecting to the database. It always seemed to use the computer name or the app pool service. I tried many many examples I found on the net and here to no avail. Even if I got that to work then I would want to use and Active Directory group over individual logins which looked to be another hurdle.
This app stores documents in a varbinary column so that full text search can be enabled at some point. The issue was with large files which are generally pictures or videos. Since you can't search text on those anyway the strategy now is to store those on the file system and all other searchable docs (.docx, .pptx, etc) will still be stored in the varbinary. I'm actually sad that I could not get filestream to work as it seems like the ideal solution. I'll come back to it some day but it really should not be so frickin complicated. :-(
The code I got working is:
Dim filePath As String = ""
Dim trxContext As Byte() = {}
Dim baseFileId As Integer
Using trxScope As New TransactionScope
Using dbConn As New SqlConnection(DigsFSConnStr)
Using dbCmd As New SqlCommand("NEW_FileStreamBaseFile", dbConn)
dbCmd.CommandType = CommandType.StoredProcedure
dbCmd.Parameters.AddWithValue("#Title", fileDesc)
dbCmd.Parameters.AddWithValue("#Summary", summary)
dbCmd.Parameters.AddWithValue("#Comments", comments)
dbCmd.Parameters.AddWithValue("#FileName", uploadedFileName)
dbCmd.Parameters.AddWithValue("#ContentType", contentType)
dbCmd.Parameters.AddWithValue("#FileExt", ext)
'dbCmd.Parameters.AddWithValue("#FileBytes", noBytes) ' now that were offloading the file byte storage to a thread
dbCmd.Parameters.AddWithValue("#UploadedByResourceID", uploadedByResourceID)
dbCmd.Parameters.AddWithValue("#UploadedByShortName", uploadedByShortName)
dbCmd.Parameters.AddWithValue("#FileAuthor", fileAuthor)
dbCmd.Parameters.AddWithValue("#TagRecID", tagRecID)
dbCmd.Parameters.AddWithValue("#UserID", samAccountName)
dbCmd.Parameters.AddWithValue("#FileDate", fileDate)
dbCmd.Parameters.AddWithValue("#FileType", fileType)
dbCmd.Parameters.AddWithValue("#FileTypeRecID", fileTypeRecId)
' Save to file system too for xod conversion
file.SaveAs(HttpContext.Current.Server.MapPath("~/files/uploaded/") & uploadedFileName)
dbConn.Open()
Using dbRdr As SqlDataReader = dbCmd.ExecuteReader(CommandBehavior.SingleRow)
dbRdr.Read()
If dbRdr.HasRows Then
filePath = dbRdr("Path")
trxContext = dbRdr("TrxContext")
json.Add("baseFileId", dbRdr("BaseFileID"))
virtualFileRecId = dbRdr("VirtualFileRecID")
dbStatus = dbRdr("status")
If dbStatus = "failure" Then
json.Add("msg", dbRdr("msg"))
End If
End If
dbRdr.Close()
End Using
' Prepare and start Task thread to write the file
If dbStatus = "success" Then
bytes = br.ReadBytes(fs.Length)
Dim task As New System.Threading.Tasks.Task(
Sub()
UpdateNewFileStreamBytes(virtualFileRecId, bytes)
End Sub)
task.Start()
json.Add("status", "success")
Else
json.Add("status", "failure")
End If
End Using
dbConn.Close()
End Using
trxScope.Complete()
End Using ' transaction commits here, not in line above
With the task procedure of:
Private Sub UpdateNewFileStreamBytes(virtualFileRecId As Integer, fileBytes As Byte())
Dim filePath As String = ""
Dim trxContext As Byte() = {}
Try
Using trxScope As New TransactionScope
Using dbConn As New SqlConnection(DigsFSConnStr)
Using dbCmd As New SqlCommand("UPD_FileStreamBaseFile", dbConn)
dbCmd.CommandType = CommandType.StoredProcedure
dbCmd.Parameters.AddWithValue("#VirtualFileRecID", virtualFileRecId)
dbConn.Open()
Using dbRdr As SqlDataReader = dbCmd.ExecuteReader(CommandBehavior.SingleRow)
dbRdr.Read()
If dbRdr.HasRows Then
filePath = dbRdr("Path")
trxContext = dbRdr("TrxContext")
End If
dbRdr.Close()
Using dest As New SqlFileStream(filePath, trxContext, FileAccess.Write)
dest.Write(fileBytes, 0, fileBytes.Length)
dest.Close()
End Using
End Using
End Using
dbConn.Close()
End Using
trxScope.Complete()
End Using
Catch ex As Exception
Elmah.ErrorSignal.FromCurrentContext().Raise(ex)
End Try

Loop through each row, create button for each record. Cannot get image from database

I have a form that I am trying to populate with a control for each item on my database (SQLCe). Problem is that one of the items I am trying to return from the database is an image. However, my original code gave me an error:
Value of type "Byte' cannot be converted to 'System.Drawing.Image'
Here is my original code
Private Sub btnCategories_Click(sender As Object, e As EventArgs) Handles btnCategories.Click
Dim dt As DataTable = ProducT_CATEGORYTableAdapter.GetData
For Each row As DataRow In dt.Rows
Dim btn As New btnCategoryTabs()
btn.lblCategoryName.Name = DirectCast(row("Category_Name"), String)
btn.lblCategoryName.Text = btn.lblCategoryName.Name
btn.picPCategoryPicture.Image = DirectCast(row("Image"), Byte) 'Error Here'
'Add categories to the Panel
flpMainPanel.Controls.Add(btn)
Next
End Sub
I am sure that I have to convert the image, so I started messing around with this bit of code:
Dim Stream As New MemoryStream()
Dim image As Byte() = CType('Can't figure out what to put here), Byte())
Stream.Write(image, 0, image.Length)
Dim bitmap As New Bitmap(Stream)
Any help will be appreciated.
Thanks.
If you have stored image data in your database then it would be a Byte() i.e. and array, not just a single Byte. You then have to convert that Byte array to an Image. You're on the right track. Here's one I prepared earlier:
Dim connection As New SqlConnection("connection string here")
Dim command As New SqlCommand("SELECT Picture FROM MyTable WHERE ID = 1", connection)
connection.Open()
Dim pictureData As Byte() = DirectCast(command.ExecuteScalar(), Byte())
connection.Close()
Dim picture As Image = Nothing
'Create a stream in memory containing the bytes that comprise the image.'
Using stream As New IO.MemoryStream(pictureData)
'Read the stream and create an Image object from the data.'
picture = Image.FromStream(stream)
End Using
http://www.vbforums.com/showthread.php?469562-Saving-Images-in-Databases&highlight=
In your case specifically, that becomes:
'Create a stream in memory containing the bytes that comprise the image.'
Using stream As New IO.MemoryStream(DirectCast(row("Image"), Byte()))
'Read the stream and create an Image object from the data.'
btn.picPCategoryPicture.Image = Image.FromStream(stream)
End Using

VB.NET retrieving varbinary data into picture box

I have a some data in SQL Server in a VARBINARY column, I just want to know how to display it into a PictureBox in VB.NET. How to do this?
Binary data looks something like:
0x1F8B0800000000000400EDBD07601C499625262F6DCA7B7F4AF54AD7E.....(and a great many more bytes to come)......
Private Sub sample()
Dim command, commandReader As New NpgsqlCommand
command.Connection = GetConnection()
command.CommandText = "select imgField from imgtable"
Dim productImageByte As Byte() = TryCast(command.ExecuteScalar, Byte())
If productImageByte IsNot Nothing Then
Using productImageStream As Stream = New System.IO.MemoryStream(productImageByte)
PPicBoxPhoto.Image = Image.FromStream(productImageStream)
End Using
End If
End Sub
NOTE : This a sample of my code that I'm using for my requirement, using PostgreSQL database and the image data type is bytea

how to update image using database in vb.net

what is the problem of this code?? i got a error for the GDI+ and i dont know to solve.
Private Sub saveEmployee()
Dim ms As New MemoryStream
PictureBox1.Image.Save(ms, PictureBox1.Image.RawFormat)--i got error in this line..A generic error occurred in GDI+.
Dim arrPic() As Byte = ms.GetBuffer()
Dim cmdEmp As New MySqlCommand
Dim sqlEmp As String
sqlEmp = "update tbl_employee set emPic=#emPic where emID='" & lbl_empID.Text & "'"
With cmdEmp
.Parameters.AddWithValue("#emPic", arrPic)
.ExecuteNonQuery()
End With
End Sub
Try replacing that line with this :
Dim bm as Bitmap = new Bitmap(PictureBox1.Image)
bm.Save(ms, PictureBox1.Image.RawFormat)
The reason could be that the Image is being used by the PictureBox. Its also good practice to have the following instead :
Using ms As MemoryStream = New MemoryStream()
Dim bm as Bitmap = new Bitmap(PictureBox1.Image)
bm.Save(ms, PictureBox1.Image.RawFormat)
Dim arrPic() As Byte = ms.GetBuffer()
Dim cmdEmp As New MySqlCommand
Dim sqlEmp As String
sqlEmp = "update tbl_employee set emPic=#emPic where emID=#emID"
With cmdEmp
.Parameters.AddWithValue("#emPic", arrPic)
.Parameters.AddWithValue("#emID", int.Parse(lbl_empID.Text))
.ExecuteNonQuery()
End With
End Using
This way the MemoryStream will get Disposed after being used. And adding #emID as a parameter is safer.
RESOLVED!!!
Bind picture box to the datasource field using the Advance tab in the DataBindings section. Use the ImageLocation property instead of image. Then change the Update mode to NEVER. but how abt the update ??? Use a textbox and hide behind the Picture box [with visible = true]. Bind textbox to same datasource. THAT IS!!!
image displays directly in picture box whilst the textbox TextChanged property handles whether there is UPDATE or Not. took me a while but it works fine now. good luck as u code... ~ SAM, GHANA