"System.OutOfMemoryException: 'Out of memory.'" 从 SQL 服务器读取图像时
"System.OutOfMemoryException: 'Out of memory.'" when reading image from SQL Server
我的 VB.NET 表单中的每个按钮都分配了图像,这些图像来自 SQL 服务器。数据类型为 varbinary(MAX)
.
这是我的代码:
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
平台为 64 位。我认为这可能与未正确处理有关,但我不确定,因为我是编码新手。
编辑显示新代码以及我如何检索多个记录:
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
您不想在更新用户界面时保持连接打开。将用户界面代码与数据库代码分开。
如果在外部 Using 块的第一行末尾放置一个逗号,则命令和连接都包含在同一块中。节省一点缩进。
您将一个整数传递给 @ID
参数,但您已将 SqlDbType
设置为 VarChar
。看起来像个问题。我将 SqlDbType
更改为 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
编辑在图像上添加处置
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
我通过不使用按钮解决了这个问题。相反,我使用图片框作为按钮并解决了问题。我猜问题是按钮不允许像图片框一样多的内存。
我的 VB.NET 表单中的每个按钮都分配了图像,这些图像来自 SQL 服务器。数据类型为 varbinary(MAX)
.
这是我的代码:
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
平台为 64 位。我认为这可能与未正确处理有关,但我不确定,因为我是编码新手。
编辑显示新代码以及我如何检索多个记录:
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
您不想在更新用户界面时保持连接打开。将用户界面代码与数据库代码分开。
如果在外部 Using 块的第一行末尾放置一个逗号,则命令和连接都包含在同一块中。节省一点缩进。
您将一个整数传递给 @ID
参数,但您已将 SqlDbType
设置为 VarChar
。看起来像个问题。我将 SqlDbType
更改为 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
编辑在图像上添加处置
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
我通过不使用按钮解决了这个问题。相反,我使用图片框作为按钮并解决了问题。我猜问题是按钮不允许像图片框一样多的内存。