2016-11-08 41 views
0
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 
+0

有幾件事,首先你要在執行查詢之前處理你的命令。你應該執行然後處理。 – Codexer

+1

'DBNull.Value()'值是屬性而不是方法 – Plutonix

+0

不是'使用'比'.Close'或'.Dispose'更習慣的選擇嗎? @Zaggler –

回答

1

您在代碼中有多個問題。爲了外觀:

不使用的GetBuffer()

正如上MSDN提到的,緩衝液可以是高達流中的數據的大小的兩倍。這會使數據庫不必要地增加額外的空值。改爲使用ToArray()

由於數據庫中的圖像必須轉換爲字節數組以及從字節數組轉換,因此可以考慮將圖像歸檔到文件夾並將名稱存儲在數據庫中。然後,您可以預先安裝存檔文件夾名稱以快速加載圖像。

而不是RawFormat,我會將它編碼爲像JPEG一樣。

使用Using

任何具有.Dispose方法通常需要被設置。這將適用於OleDBCommand對象(MemStream實際上不需要處理,但這是一個實現細節)。

Using塊incoporate DimNewDispose在一個方便的,易於使用的塊:

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

第一行聲明一個foo變量,並創建的FooBar一個實例,它可以在塊內使用。最後,它會自動處理。

不要使用全局的DBCommand對象

您的代碼並不顯示cmd正在申報或創建的,所以它必須是一個窗體級別的對象。 不要那樣做。除非您的所有應用程序確實是一回事,否則沒有任何關於DBCommand對象的可重用內容。

在代碼中添加2個參數。下一次使用它時,它仍然可以有2個,並且代碼將會添加2個,這比SQL查詢所需要的更多。在這種情況下,代碼將處理它,但意味着下次您參考它時,您將獲得ObjectDisposedException

  • 如前所述,您的代碼調用DisposeExecuteNonQuery將崩潰 - 你不能用一個釋放的對象。

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() 
  • 由於命令對象是無用的,而不查詢和連接兩者,我更喜歡在構造函數中傳遞它們。它使代碼更短以及確保它具有它所需要的功能
  • 還應該創建,使用和每次處理連接
  • 創建一個方便的擴展方法可以將圖像轉換爲字節數組
相關問題