【问题标题】:Class 'System.DBNull' cannot be indexed because it has no default property类 'System.DBNull' 不能被索引,因为它没有默认属性
【发布时间】:2016-11-11 01:07:32
【问题描述】:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        cn.Open()
        Dim arrimage() As Byte
        Dim ms As New MemoryStream()
        If (pb1.Image IsNot Nothing) Then
            pb1.Image.Save(ms, pb1.Image.RawFormat)
            arrimage = ms.GetBuffer
            ms.Close()
        End If
        With cmd
            .Connection = cn
            .CommandText = "INSERT INTO [Example]([PName],[Pic])VALUES(@a2,@a1)"
            .Parameters.Add("a0", OleDbType.VarChar).Value = tName.Text
            .Parameters.Add("a1", OleDbType.Binary).Value = IIf(pb1.Image IsNot Nothing, arrimage, DBNull.Value())
            .Dispose()
            .ExecuteNonQuery()
        End With
        cn.Close()
    End Sub

【问题讨论】:

  • 有几件事,首先你要在执行查询之前处理你的命令。您应该执行然后处置。
  • DBNull.Value() 值是属性而不是方法
  • Using 不是比.Close.Dispose 更惯用的选择吗? @Zaggler
  • @ZevSpitz 当然是,它确保对象得到处理。目前,它永远不会按照 OP 当前的方式执行,这就是我的观点。
  • @Plutonix 知道我该怎么做吗?我正在尝试使用 vb.net 将图像保存在 msaccess 中

标签: vb.net


【解决方案1】:

您的代码中有多个问题。按出场顺序:

不要使用 GetBuffer()

MSDN 中所述,缓冲区的大小可以是流中数据的两倍。这将不必要地用额外的空值使数据库膨胀。请改用ToArray()

由于数据库中的图像必须与字节数组相互转换,请考虑将图像归档到文件夹并仅将名称存储在数据库中。然后,您可以添加存档文件夹名称以快速加载图像。

而不是 RawFormat,我会将其编码为 JPEG 之类的格式。

使用Using

任何具有.Dispose 方法的东西通常都需要被处理掉。这将适用于OleDBCommand 对象(MemStream 确实不需要被释放,但这是一个实现细节)。

Using 块将DimNewDispose 合二为一,易于使用:

Using foo As New FooBar()
   ...
End Using

第一行声明了一个foo 变量,并创建了一个FooBar 的实例,您可以在块中使用它。最后,它会被自动处理掉。

不要使用全局 DBCommand 对象

您的代码没有显示 cmd 被声明或创建,因此它必须是表单级对象。 不要这样做DBCommand 对象没有什么可重用的,除非您的应用程序所做的只是一件事。

在代码中添加 2 个参数。下次你去使用它时,它可能仍然有这 2 个,并且代码将添加 2 个,这比 SQL 查询所需的要多。在这种情况下,代码会处理它,但 that 意味着下次你去引用它时,你会得到一个ObjectDisposedException

  • 如前所述,您的代码调用 Dispose 之前 ExecuteNonQuery 会崩溃 - 您不能使用已处置的对象。

DBNull.Value 不是方法

至于编译器错误,你有这个:

IIf(pb1.Image IsNot Nothing, arrimage, DBNull.Value())

DBNull.Value 是属性,而不是方法,因此不需要括号。此外,您应该使用“新”If 运算符而不是旧的IIF 函数。运算符被短路,因此不适用的部分/子句被忽略:

' should evaluate the data (arrimage) not its source
If(pb1.Image IsNot Nothing, arrimage, DBNull.Value)   ' no parens

修改后的代码:

cn.Open()
Dim arrimage() As Byte = Nothing

If (pb.Image IsNot Nothing) Then
    Using ms As New MemoryStream()
        pb.Image.Save(ms, ImageFormat.Jpeg)
        arrimage = ms.ToArray()
    End Using
End If

Dim sql = "INSERT INTO [Example]([PName],[Pic]) VALUES (@a2,@a1)"

Using cmd As New OleDbCommand(sql, cn)
    cmd.Parameters.Add("a0", OleDbType.VarChar).Value = tName.Text
    If arrimage IsNot Nothing Then
        cmd.Parameters.Add("a1", OleDbType.VarBinary).Value = arrimage 
    Else
        cmd.Parameters.Add("a1", OleDbType.VarBinary).Value = DBNull.Value
    End If
    cmd.ExecuteNonQuery()
End Using

cn.Close()
  • 由于命令对象没有查询和连接都是无用的,我更喜欢在构造函数中传递它们。它使代码更短,并确保它有它需要的东西
  • 也应该每次都创建、使用和处理连接
  • 创建一个方便的扩展方法来将图像转换为字节数组也很容易

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-27
    • 1970-01-01
    • 1970-01-01
    • 2019-08-06
    相关资源
    最近更新 更多