You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VB.NET Access登录系统头像跨PictureBox传递及DBNull转换报错解决

问题根因
  • 注册逻辑错误:新增用户记录后未将头像更新到该条记录,而是单独插入了一条仅含头像的新记录,导致对应用户的头像字段为NULL,登录查询时就会触发DBNull转Byte[]的报错
  • 缺少非空校验:登录查询时直接将头像字段值强转为Byte(),未提前判断字段是否为NULL
  • Form2头像赋值逻辑写反:Form2加载时将空的头像控件值赋值给全局变量,而非用全局变量给控件赋值,导致Form2始终显示空头像
  • 头像存储缺陷:使用MemoryStream.GetBuffer()获取字节数组,会包含冗余的未使用字节,应该用ToArray()获取准确的流内容
修复代码

修改Form1的saveimage方法

改为更新对应用户的头像字段,而非插入新记录

Private Sub saveimage(userName As String)
    If PictureBox1.Image Is Nothing Then
        Throw New Exception("请先选择头像")
    End If
    Dim arrimage() As Byte
    Using mstream As New System.IO.MemoryStream
        If PictureFormat.ToLower = ".png" Then
            PictureBox1.Image.Save(mstream, System.Drawing.Imaging.ImageFormat.Png)
        ElseIf PictureFormat.ToLower = ".jpg" Then
            PictureBox1.Image.Save(mstream, System.Drawing.Imaging.ImageFormat.Jpeg)
        End If
        ' 用ToArray代替GetBuffer,获取准确的字节内容
        arrimage = mstream.ToArray()
    End Using
    ' 改用Update语句更新对应用户的头像字段
    Using con As New OleDbConnection(cnStr),
            cmd As New OleDbCommand("Update TBLoginPic set Imagen = @Imagen where Usuario = @Usuario", con)
        With cmd
            .Parameters.Add("@Imagen", OleDbType.Binary).Value = arrimage
            .Parameters.Add("@Usuario", OleDbType.VarChar).Value = userName
            con.Open()
            .ExecuteNonQuery()
        End With
    End Using
End Sub

修改Form1的注册按钮逻辑

传入当前注册的用户名更新头像,增加必填校验

Private Sub BtnRegistrarse_Click(sender As Object, e As EventArgs) Handles BtnRegistrarse.Click
    If String.IsNullOrWhiteSpace(TBusuario.Text) OrElse String.IsNullOrWhiteSpace(TBcontraseña.Text) Then
        MsgBox("用户名和密码不能为空")
        Exit Sub
    End If
    If PictureBox1.Image Is Nothing Then
        MsgBox("请先选择头像")
        Exit Sub
    End If

    Me.TBLoginPicBindingSource.AddNew()
    Me.TBLoginPicBindingSource.EndEdit()
    Me.TBLoginPicTableAdapter.Update(Me.DBLoginPicDataSet)

    Try
        saveimage(TBusuario.Text)
    Catch ex As Exception
        MessageBox.Show(ex.Message)
        Exit Sub
    End Try
    MsgBox("注册成功,头像已保存")
End Sub

修改Form1的登录按钮逻辑

增加DBNull校验,避免强转报错

Private Sub BtnLoguearse_Click(sender As Object, e As EventArgs) Handles BtnLoguearse.Click
    If Me.TBLoginPicTableAdapter.BuscarDatos(Me.DBLoginPicDataSet.TBLoginPic, TBusuario.Text, TBcontraseña.Text) Then
        Dim dt As DataTable
        Try
            dt = GetDataByName(TBusuario.Text)
            If dt.Rows.Count = 0 Then
                MsgBox("未查询到用户信息")
                Exit Sub
            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message)
            Exit Sub
        End Try

        TBusuario.Text = dt(0)("Usuario").ToString
        ' 增加DBNull判断
        If Not IsDBNull(dt(0)("Imagen")) Then
            Dim arrimage = DirectCast(dt(0)("Imagen"), Byte())
            Using mstream As New System.IO.MemoryStream(arrimage)
                PictureBox1.Image = Image.FromStream(mstream)
            End Using
        Else
            ' 可提前添加默认头像到项目资源,此处赋值默认头像
            PictureBox1.Image = My.Resources.DefaultAvatar
        End If

        Form2.Show()
        _selectedImage = PictureBox1.Image
        Me.Close()
    Else
        MsgBox("账号或密码错误")
    End If
End Sub

修改Form2的Load事件逻辑

修正头像赋值方向

Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    ' 不需要重复加载表数据可以删除此行,减少冗余查询
    ' Me.TBLoginPicTableAdapter.Fill(Me.DBLoginPicDataSet.TBLoginPic)
    If _selectedImage IsNot Nothing Then
        PBPerfil.Image = _selectedImage
    End If
End Sub

优化头像选择逻辑

避免用户点取消时报错

Private Sub FillPictureBoxFromFile()
    With OpenFileDialog1
        .Filter = "(*.jpg)|*.jpg|(*.png)|*.png"
        .RestoreDirectory = True
        .Title = "Select a file to open"
        If .ShowDialog = DialogResult.OK Then
            PictureBox1.Image = Image.FromFile(.FileName)
            PictureFormat = Path.GetExtension(.FileName)
        End If
    End With
End Sub
其他优化建议
  • 数据库连接路径不要写死,改用相对路径或者配置文件存储,避免换环境就无法访问数据库
  • 密码不要明文存储在数据库,建议加盐哈希后存储,提升安全性
  • 全局变量传值可以改成Form2构造函数传参,更安全,避免全局变量被意外修改
  • 所有实现了IDisposable接口的对象(比如MemoryStream、数据库连接)都用Using包裹,自动释放资源避免内存泄漏

内容的提问来源于stack exchange,提问作者THEwed123wet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 07:15:07