I have images assigned to every button in my VB.NET form, the images come from SQL Server. The data type is varbinary(MAX).
This is my code:
Using con As New SqlConnection("con string")
Dim sql As String = "SELECT * FROM Inventory WHERE ID=#ID"
Using cmd As New SqlCommand(sql, con)
cmd.Parameters.Add("#ID", SqlDbType.VarChar).Value = 3
con.Open()
Using myreader As SqlDataReader = cmd.ExecuteReader()
If myreader.Read() AndAlso Not DBNull.Value.Equals(myreader("Image")) Then
Boton3.Text = myreader("Item")
Boton3.Enabled = myreader("ONOFF")
Dim ImgSql() As Byte = DirectCast(myreader("Image"), Byte())
Using ms As New MemoryStream(ImgSql)
Boton3.BackgroundImage = Image.FromStream(ms)
con.Close()
End Using
Else
Boton3.Text = myreader("Item")
Boton3.BackgroundImage = Nothing
Boton3.Enabled = myreader("ONOFF")
End If
End Using
End Using
End Using
The platform is 64bit. I'm thinking it might have to do with not disposing properly, but I'm not sure since I'm new to coding.
EDIT SHOWING NEW CODE AND HOW I RETRIVE MORE THAN ONE RECORD:
Private Sub Button12_Click(sender As Object, e As EventArgs) Handles Button12.Click
Dim dt As DataTable
Try
dt = GetInventoryDataByID(1)
Catch ex As Exception
MessageBox.Show(ex.Message)
Exit Sub
End Try
If dt.Rows.Count > 0 Then
Boton1.Text = dt.Rows(0)("Articulo").ToString
Boton1.Enabled = CBool(dt.Rows(0)("ONOFF"))
If Not DBNull.Value.Equals(dt.Rows(0)("Imagen")) Then
Dim ImgSql() As Byte = DirectCast(dt.Rows(0)("Imagen"), Byte())
Using ms As New MemoryStream(ImgSql)
Boton1.BackgroundImage = Image.FromStream(ms)
End Using
Else
Boton1.BackgroundImage = Nothing
End If
Else
MessageBox.Show("No records returned")
End If
Dim dt2 As DataTable
Try
dt2 = GetInventoryDataByID(2)
Catch ex As Exception
MessageBox.Show(ex.Message)
Exit Sub
End Try
If dt2.Rows.Count > 0 Then
Boton2.Text = dt2.Rows(0)("Articulo").ToString
Boton2.Enabled = CBool(dt2.Rows(0)("ONOFF"))
If Not DBNull.Value.Equals(dt2.Rows(0)("Imagen")) Then
Dim ImgSql() As Byte = DirectCast(dt2.Rows(0)("Imagen"), Byte())
Using ms As New MemoryStream(ImgSql)
Boton2.BackgroundImage = Image.FromStream(ms)
End Using
Else
Boton2.BackgroundImage = Nothing
End If
Else
MessageBox.Show("No records returned")
End If
End Sub
Private Function GetInventoryDataByID(id As Integer) As DataTable
Dim dt As New DataTable
Dim sql As String = "SELECT Imagen, Articulo, ONOFF FROM Inventario WHERE ID=#ID"
Using con As New SqlConnection("CON STRING"),
cmd As New SqlCommand(sql, con)
cmd.Parameters.Add("#ID", SqlDbType.Int).Value = id
con.Open()
Using myreader As SqlDataReader = cmd.ExecuteReader()
dt.Load(myreader)
End Using
End Using
Return dt
End Function
End Class
You don't want to hold a connection open while you update the user interface. Separate you user interface code from your database code.
If you put a comma at the end of the first line of the outer Using block, both the command and the connection are included in same block. Saves a bit of indenting.
You are passing an integer to the #ID parameter but you have set the SqlDbType as a VarChar. Looks like a problem. I changed the SqlDbType to Int.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim dt As DataTable
Try
dt = GetInventoryDataByID(3)
Catch ex As Exception
MessageBox.Show(ex.Message)
Exit Sub
End Try
If dt.Rows.Count > 0 Then
Boton3.Text = dt.Rows(0)("Item").ToString
Boton3.Enabled = CBool(dt.Rows(0)("ONOFF"))
If Not DBNull.Value.Equals(dt.Rows(0)("Image")) Then
Dim ImgSql() As Byte = DirectCast(dt.Rows(0)("Image"), Byte())
Using ms As New MemoryStream(ImgSql)
Boton3.BackgroundImage = Image.FromStream(ms)
End Using
Else
Boton3.BackgroundImage = Nothing
End If
Else
MessageBox.Show("No records returned")
End If
End Sub
Private Function GetInventoryDataByID(id As Integer) As DataTable
Dim dt As New DataTable
Dim sql As String = "SELECT * FROM Inventory WHERE ID=#ID"
Using con As New SqlConnection("con string"),
cmd As New SqlCommand(sql, con)
cmd.Parameters.Add("#ID", SqlDbType.Int).Value = id
con.Open()
Using myreader As SqlDataReader = cmd.ExecuteReader()
dt.Load(myreader)
End Using
End Using
Return dt
End Function
EDIT Add Dispose on image
If Not DBNull.Value.Equals(dt.Rows(0)("Image")) Then
Dim ImgSql() As Byte = DirectCast(dt.Rows(0)("Image"), Byte())
Using ms As New MemoryStream(ImgSql)
If Boton3.BackgroundImage IsNot Nothing Then
Boton3.BackgroundImage.Dispose()
End If
Boton3.BackgroundImage = Image.FromStream(ms)
End Using
Else
If Boton3.BackgroundImage IsNot Nothing Then
Boton3.BackgroundImage.Dispose()
End If
End If
I resolved this issue by simply not using buttons. Instead I used pictureboxes as buttons and that resolved the issue. Im guesssing the problem is that buttons don't allow as much memory as pictureboxes.
I'm creating a system where user selects books that he needs. As I have developed my system, creating an Admin Module is as important to the system.
Here I have my own problem where I want to insert data from a DataGridView that is already connected to the database which is MS Access. It doesn't give me errors but when I run it and tested it, it appears that something is not write of processing on the program. The error was
System.InvalidOperationException: 'Rows cannot be programmatically added to the DataGridView's rows collection when the control is data-bound.'
What I actually want is that the DataGridView can be updated at the same time with the MS Access that is connected to.
Imports System.Data.OleDb
Public Class Register
Dim provider As String
Dim datafile As String
Dim connString As String
Dim myConnection As OleDbConnection = New OleDbConnection
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
If ComboBox1.Text.Equals("TVL12") Then
TVL12.Show()
End If
End Sub
Private Sub addBtn_Click(sender As Object, e As EventArgs) Handles addBtn.Click
Admin.table.Rows.Add(booknameReg.Text, authorReg.Text, publisherReg.Text, subjectcodeReg.Text, priceReg.Text, discountamountReg.Text)
'TVL12.BookListTVL.Rows.Add(booknameReg.Text, authorReg.Text, publisherReg.Text, subjectcodeReg.Text, priceReg.Text, discountamountReg.Text)'
provider = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source="
datafile = "C:\Users\acjfc\OneDrive\Desktop\thesis\DATABASE\BookLists.accdb"
connString = provider & datafile
myConnection.ConnectionString = connString
myConnection.Open()
Dim str As String
str = "Insert into TVL12([Book Name],[Author],[Publisher],[Subject Code],[Price],[DiscountAmount]) Values (?,?,?,?,?,?)"
Dim cmd As OleDbCommand = New OleDbCommand(str, myConnection)
cmd.Parameters.Add(New OleDbParameter("Book Name", CType(booknameReg.Text, String)))
cmd.Parameters.Add(New OleDbParameter("Author", CType(authorReg.Text, String)))
cmd.Parameters.Add(New OleDbParameter("Publisher", CType(publisherReg.Text, String)))
cmd.Parameters.Add(New OleDbParameter("Subject Code", CType(subjectcodeReg.Text, String)))
cmd.Parameters.Add(New OleDbParameter("Price", CType(priceReg.Text, String)))
cmd.Parameters.Add(New OleDbParameter("DiscountAmount", CType(discountamountReg.Text, String)))
Try
cmd.ExecuteNonQuery()
cmd.Dispose()
myConnection.Close()
booknameReg.Clear()
authorReg.Clear()
publisherReg.Clear()
subjectcodeReg.Clear()
priceReg.Clear()
discountamountReg.Clear()
Catch ex As Exception
MsgBox(ex.Message)
End Try
Admin.MainData.DataSource = Admin.table
End Sub
End Class
As you can see, the code "TVL12.BookListTVL.Rows.Add(booknameReg.Text, authorReg.Text, publisherReg.Text, subjectcodeReg.Text, priceReg.Text, discountamountReg.Text)" has been turned into comment for it wouldn't work if I remove the '' thing. Although I've done it with the other one which is not really connected to database. Can someone help me what the problem is here?
According to your description, you want to update the datagridview when you add data to database.
You can refer to the modified code I wrote.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim newtable = New DataTable()
provider = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source="
datafile = "C:\Users\testuser\Documents\BookLists.accdb"
connString = provider & datafile
myConnection.ConnectionString = connString
myConnection.Open()
Dim str As String
'str = "Insert into TVL12([Name],[Age],[StuId]) Values (?,?,?)"
'Dim cmd As OleDbCommand = New OleDbCommand(str, myConnection)
'cmd.Parameters.Add(New OleDbParameter("Name", CType("test4", String)))
'cmd.Parameters.Add(New OleDbParameter("Age", CType(26, Int32)))
'cmd.Parameters.Add(New OleDbParameter("StuId", CType(1004, Int32)))
Try
'cmd.ExecuteNonQuery()
str = "Select * from TVL12"
Dim cmd As OleDbCommand = New OleDbCommand(str, myConnection)
Dim da As OleDbDataAdapter = New OleDbDataAdapter()
da.SelectCommand = cmd
da.Fill(newtable)
cmd.Dispose()
myConnection.Close()
Catch ex As Exception
MsgBox(ex.Message)
End Try
DataGridView1.DataSource = newtable
End Sub
You have an add button that inserts a new record in the database table. Try to keep your subs and functions doing only one thing. You can call DisplayData after the insert and also in the Form.Load.
I question the datatypes of some of the fields in your table. If Subject Code is a number it should be an Integer. Price and Discount Amount should be Decimal.
I had to guess what type your parameters are. Check your database for the real types. The last parameter of the .Add method is the size of the field. It is not necessary to call .ToString on a .Text property. It is already a string.
Using...End Using blocks close and dispose you database objects even it there is an error.
Private Sub addBtn_Click(sender As Object, e As EventArgs) Handles addBtn.Click
Try
Using myConnection As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\acjfc\OneDrive\Desktop\thesis\DATABASE\BookLists.accdb"),
cmd As New OleDbCommand("Insert into TVL12 ([Book Name],[Author],[Publisher],[Subject Code],[Price],[DiscountAmount]) Values (?,?,?,?,?,?)", myConnection)
cmd.Parameters.Add("BookName", OleDbType.VarChar, 200).Value = booknameReg.Text
cmd.Parameters.Add("Author", OleDbType.VarChar, 200).Value = authorReg.Text
cmd.Parameters.Add("Publisher", OleDbType.VarChar, 200).Value = publisherReg.Text
cmd.Parameters.Add("SubjectCode", OleDbType.VarChar, 200).Value = subjectcodeReg.Text
cmd.Parameters.Add("Price", OleDbType.VarChar, 100).Value = priceReg.Text
cmd.Parameters.Add("DiscountAmount", OleDbType.VarChar, 50).Value = discountamountReg.Text
myConnection.Open()
cmd.ExecuteNonQuery()
End Using
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
ClearTextBoxes()
DisplayData()
End Sub
Private Sub ClearTextBoxes()
booknameReg.Clear()
authorReg.Clear()
publisherReg.Clear()
subjectcodeReg.Clear()
priceReg.Clear()
discountamountReg.Clear()
End Sub
Private Sub DisplayData()
Dim dt As New DataTable
Using myConnection As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\acjfc\OneDrive\Desktop\thesis\DATABASE\BookLists.accdb"),
cmd As New OleDbCommand("Select * From TVL12", myConnection)
myConnection.Open()
dt.Load(cmd.ExecuteReader)
End Using
DataGridView1.DataSource = dt
End Sub
Public Function QueryDataSet(ByVal strSQL As String) As DataSet
Dim ds As New DataSet
Dim dtAdapter As New SqlDataAdapter
objConn = New SqlConnection
With objConn
.ConnectionString = strConn
.Open()
End With
objCmd = New SqlCommand
With objCmd
.Connection = objConn
.CommandText = strSQL
.CommandType = CommandType.Text
End With
dtAdapter.SelectCommand = objCmd
dtAdapter.Fill(ds)
objConn.Close()
objConn.Dispose()
SqlConnection.ClearPool(objConn)
objConn = Nothing
Return ds
End function
The above is in the class
How can I fix my function that solve the Max Pool Size is Full on my server?
Please Help me.
Use following code
Public Function QueryDataSet(ByVal strSQL As String) As DataSet
Dim ds As New DataSet
Dim dtAdapter As New SqlDataAdapter
Try
objConn = New SqlConnection
With objConn
.ConnectionString = strConn
.Open()
End With
objCmd = New SqlCommand
With objCmd
.Connection = objConn
.CommandText = strSQL
.CommandType = CommandType.Text
End With
dtAdapter.SelectCommand = objCmd
dtAdapter.Fill(ds)
objConn.Close()
objConn.Dispose()
SqlConnection.ClearPool(objConn)
objConn = Nothing
Catch ex As Exception
MessageBox.Show(ex.Message)
Finally
objConn.Close()
objConn.Dispose()
SqlConnection.ClearPool(objConn)
objConn = Nothing
End Try
Return ds
End function
or Add MaxPoolSize=abc in the Connection String.
I'm trying to populate a combobox with data from SQL Server. This is my code so far. There are asterisks around the errors. Also, ignore the comments.
Private Sub frmOriginal_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim connetionString As String = Nothing
Dim sqlcon As SqlConnection
Dim command As SqlCommand
Dim adapter As New SqlDataAdapter()
Dim ds As New DataSet()
Dim i As Integer = 0
Dim sql As String = Nothing
connetionString = "Data Source = RENEE\SQLEXPRESS;Initial Catalog=Stocks;Integrated Security = True"
sql = "select * from TickerSymbol"
sqlcon = New SqlConnection(connetionString)
Try
sqlcon.Open()
command = New SqlCommand(sql, sqlcon)
adapter.SelectCommand = command
adapter.Fill(ds)
adapter.Dispose()
command.Dispose()
sqlcon.Close()
cboID.DataSource = ds.Tables(0)
cboID.ValueMember = "TickerSymbol"
cboID.DisplayMember = "TickerSymbol"
Catch ex As Exception
'MessageBox.Show("Can not open connection ! ")'
End Try
End Sub
Private Sub cboID_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboID.SelectedIndexChanged
Dim dr As SqlDataReader
Dim command As New SqlCommand *(queryString, connection)*
Dim dataReader As SqlDataReader = command.ExecuteReader()
Dim sqlcon As SqlConnection
Dim cmd As SqlCommand
sqlcon = New SqlConnection
sqlcon.ConnectionString = "Data Source = RENEE\SQLEXPRESS;Initial Catalog=Stocks;Integrated Security = True"
Try
sqlcon.Open()
cmd = New SqlCommand
cmd.CommandText = " select * from TickerSymbol where TickerSymbol = '" & cboID.Text & "'"
cmd = New SqlCommand(cmd.CommandText, sqlcon)
dr = cmd.ExecuteReader
While dr.Read()
'TxtID.Text = dr.GetInt32(0)'
'TxtSN.Text = dr.GetString(1)'
'TxtGender.Text = dr.GetString(2)'
'TxtPhone.Text = dr.GetInt32(3)'
'TxtAdrress.Text = dr.GetString(4)'
lblCompanyName.Text = dataReader.GetString(1)
lblPurchasePrice.Text = dataReader.GetSqlMoney(2)
lblQtyPurchased.Text = dataReader.GetInt32(3)
lblPurchaseDate.Text = dataReader.GetDateTime(4)
End While
sqlcon.Close()
Catch ex As SqlException
MessageBox.Show(ex.Message)
End Try
sqlcon.Dispose()
End Sub
Please use parameterized queries as this will format values properly e.g. apostrophes in text will escape properly with parameters while without you must handle them, dates will be formatted properly too. Code is much cleaner also.
Example, syntax for Framework 3.5 and higher. If a connection string is used more than once then consider placing it in a private variable or under My.Settings under project properties.
Using cn As New SqlConnection With {.ConnectionString = "Data Source = RENEE\SQLEXPRESS;Initial Catalog=Stocks;Integrated Security = True"}
Using cmd As New SqlCommand With {.Connection = cn, .CommandText = "select * from TickerSymbol where TickerSymbol = #TickerSymbol"}
cmd.Parameters.AddWithValue("#TickerSymbol", cboID.Text)
cn.Open()
Dim dr As SqlDataReader = cmd.ExecuteReader
If dr.HasRows Then
While dr.Read
'
'
'
End While
End If
End Using
End Using
may this code explain my problem,
dim dgv1 as new datagridview
dim dgv2 as new datagridview
dim dgv3 as new datagridview
dim dgv4 as new datagridview
sub processData()
conn = new sqlconnection(strcon)
conn1 = new sqlconnection(byconn)
conn.open
conn1.open
dim trans as sqltransaction = conn.begintransaction
dim trans1 as sqltransaction = conn1.begintransaction
try
dim con1 as new sqlconnection(strconn)
con1.open
dim cmd as new sqlcommand("some query",con1)
cmd.commandtype = commandtype.storedprocedure
dim da as new sqldataadapter(cmd)
dim dt as new datatable
da.fill(dt)
con1.close
dgv1.datasource = dt
for i as integer = 0 to dgv1.rowcount -1
getData2(i)
for j as integer = 0 to dgv2.rowcount -1
getData34()
end for
saveData1(i,conn,trans)
saveData2(conn1,trans1)
next
trans.commit
trans1.commit
conn.close
conn1.close
catch ex as exception
trans.rollback
trans1.rollback
conn.close
conn1.close
end try
end sub
sub getData2(i as integer)
dim con1 as new sqlconnection(strconn)
con1.open
dim cmd as new sqlcommand("some query",con1)
cmd.commandtype = commandtype.storedprocedure
cmd.parameters.addwithvalue("#PARAM",dgv1.item(0,i).value)
dim da as new sqldataadapter(cmd)
dim dt as new datatable
da.fill(dt)
con1.close
dgv2.datasource = dt
end sub
sub getdata34(i as integer)
dim con1 as new sqlconnection(strconn)
con1.open
dim cmd as new sqlcommand("some query",con1)
cmd.commandtype = commandtype.storedprocedure
cmd.parameters.addwithvalue("#PARAM",dgv2.item(0,i).value)
cmd.parameters.addwithvalue("#TYPE","LEFT")
dim da as new sqldataadapter(cmd)
dim dt as new datatable
da.fill(dt)
dgv3.datasource = dt
cmd =new sqlcommand("some query",con1)
cmd.commandtype = commandtype.storedprocedure
cmd.parameters.addwithvalue("#PARAM",dgv2.item(0,i).value)
cmd.parameters.addwithvalue("#TYPE","RIGHT")
da =new sqldataadapter(cmd)
dt =new datatable
da.fill(dt)
dgv4.datasource = dt
con1.close
end sub
sub saveData1(i as integer,cn as sqlconnection, trans as sqltransaction)
'some query with transaction
end sub
sub saveData2(cn as sqlconnection, trans as sqltransaction)
'some query with transaction
end sub
While processData called, in function getData2 and getData34 always give me timeout error message. adding timeout in sqlcommand not help me.
adding OPTION (RECOMPILE) in stored procedure also not help.
Perhaps, I miss something.