首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

解決 MySQL Connector/NET 寫入 BLOB 圖片報「索引超出陣列界限」Bug

     編輯:MySQL 資料庫相關知識

使用 MySQL Connector/NET 將圖片以 byte[] 寫入 BLOB 欄位時,拋出 IndexOutOfRangeException: 索引超出了陣列界限。經排查,根因在於參數物件的 Size 屬性對二進位類型的錯誤處理。本文記錄調試過程與通用修正方案。

問題重現

// 簡化版資料存取代碼
using (MySqlConnection conn = new MySqlConnection(connStr))
using (MySqlCommand cmd = new MySqlCommand("INSERT INTO d1(img, name) VALUES(@img, @name)", conn))
{
    byte[] imgData = new WebClient().DownloadData("https://example.com/image.gif");
    cmd.Parameters.AddWithValue("@img", imgData);  // 此處拋出例外
    cmd.Parameters.AddWithValue("@name", "test");
    conn.Open();
    cmd.ExecuteNonQuery();
}

調試發現

深入 Connector/NET 原始碼(或反編譯),參數建立流程如下:

DbParameter para = factory.CreateParameter();
para.ParameterName = "@img";
para.Value = imgData;
para.DbType = DbType.Binary;  // 對應 BLOB

// 問題關鍵:框架通用邏輯會嘗試設定 Size
if (size > -1) para.Size = size;  // size 為 byte[].Length

MySQL 驅動在處理 DbType.Binary 且設定 Size 時,內部陣列索引計算錯誤,導致越界。其他資料庫(SQL Server、Oracle、PostgreSQL)均正常。

修正方案

在參數建立邏輯中,**跳過二進位類型的 Size 設定**:

if (dbType != DbType.Binary && size > -1)
{
    para.Size = size;
}

或針對 MySQL 專用參數類別:

var para = new MySqlParameter("@img", MySqlDbType.Blob) { Value = imgData };
// 不設定 para.Size

驗證結果

  • 修正後,圖片寫入、讀取、二進位比對均正常。
  • 同樣修正適用於 VARBINARY、LONGBLOB 等二進位類型。
  • 文字類型(VARCHAR、TEXT)仍需正確設定 Size 以利參數化計畫重用。

多資料庫框架設計建議

  • 建立 IDbParameterBuilder 介面,各資料庫實作自訂 ConfigureParameter 邏輯。
  • MySQL 實作中過濾 DbType.Binary、DbType.Object 的 Size 設定。
  • 單元測試覆蓋:BLOB 寫入/讀取、超大物件(>16MB 需調整 max_allowed_packet)、NULL 值處理。

延伸知識

MySQL 8.0 的 caching_sha2_password 驗證外掛與 TLS 連線下,大物件傳輸更穩定。若仍遇問題,檢查 max_allowed_packet(預設 4MB/64MB)與 net_buffer_length 設定。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved