使用 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 邏輯。DbType.Binary、DbType.Object 的 Size 設定。max_allowed_packet)、NULL 值處理。MySQL 8.0 的 caching_sha2_password 驗證外掛與 TLS 連線下,大物件傳輸更穩定。若仍遇問題,檢查 max_allowed_packet(預設 4MB/64MB)與 net_buffer_length 設定。