如何使用C#或VB.NET将DataGridView图像单元格内容保存到SQL Server
问题原因
你现有代码的核心错误出在图像转字节数组以及MemoryStream的错误使用上,具体问题如下:
- 错误使用
MemoryStream.Read方法:你没有先把图像数据写入MemoryStream,直接执行读操作必然拿不到有效数据,且ImageConverter.ConvertTo转换Image对象到Byte()本身就可以直接得到正确的字节数组,不需要多余的MemoryStream读操作 - 调用
ms.GetBuffer()会返回MemoryStream的整个分配缓冲区,包含大量未使用的空白字节,即使前面逻辑正确拿到的也是无效的脏数据 - 注意参数名与SQL语句的对应:你数据库里的字段是
profpic,代码里参数名是@profpict,要确认SQL语句里的参数名是不是和这里一致 - 没有对
DataGridView图像列的空值做判断,若行里没有图像会直接抛出转换异常
修正后的代码
' 先判断图像列是否有有效值 If Not IsDBNull(.Rows(iLoop).Cells(5).Value) AndAlso .Rows(iLoop).Cells(5).Value IsNot Nothing Then cmd1.Parameters.AddWithValue("@empcod", .Rows(iLoop).Cells(0).Value) cmd1.Parameters.AddWithValue("@empnam", .Rows(iLoop).Cells(1).Value) cmd1.Parameters.AddWithValue("@empdep", .Rows(iLoop).Cells(3).Value) cmd1.Parameters.AddWithValue("@empdob", .Rows(iLoop).Cells(2).Value) ' 直接用ImageConverter转成字节数组,不需要多余的MemoryStream操作 Dim imgCon As New ImageConverter() Dim data As Byte() = DirectCast(imgCon.ConvertTo(.Rows(iLoop).Cells(5).Value, GetType(Byte())), Byte()) ' 若你需要用MemoryStream的写法(可选),正确写法如下: ' Dim bmp As Bitmap = DirectCast(.Rows(iLoop).Cells(5).Value, Bitmap) ' Dim ms As New MemoryStream() ' bmp.Save(ms, Imaging.ImageFormat.Jpeg) ' 可根据需求调整存储的图片格式 ' Dim data As Byte() = ms.ToArray() ' 必须用ToArray,不要用GetBuffer,只返回有效数据 ' ms.Dispose() Dim p As New SqlParameter("@profpict", SqlDbType.Image) p.Value = data cmd1.Parameters.Add(p) ' 插入成功时ExecuteNonQuery会返回1,0代表没有行受影响,说明SQL语句或参数存在错误 Dim affectRows As Integer = cmd1.ExecuteNonQuery() cmd1.Parameters.Clear() ' 每次循环执行完要清空参数,避免下次循环参数重复报错 End If
额外注意事项
- 确认你的
cmd1对应的SQL语句是正确的,参数名@profpict要和SQL里写的参数名完全匹配,不要和数据库字段名搞混 SqlDbType.Image类型已经被微软标记为过时,后续版本会移除,建议把数据库字段类型改成VARBINARY(MAX),参数类型改成SqlDbType.VarBinary,使用逻辑完全一致,兼容性更好- 如果你的DataGridView图像列存的是Web URL的字符串而不是Image对象,要先下载URL对应的图片转成Image对象再做转换,不要直接传URL字符串做转换
内容的提问来源于stack exchange,提问作者mathewsys
相关产品推荐
相关产品推荐

