2020年12月18日 星期五

[C# Windows Forms]OleDbCommand對Access執行有Parameters的SQL語法不會正常工作的情況

     最近朋友希望找我幫忙開發小工具,主要裝在筆電上用來協助他日常工作。考慮到能夠快速開發並配合簡易的資料庫,我想到是用WindowForms+Access來開發。想起之前工作寫WindowForms時還在用VB6(語言VB)開發,這一次難得有機會打算嘗試用較新的Visual studio 2019(語言C#)看看。

     在VB6時通常是用RecordSet來和資料庫溝通,如今換到較新的VS2019後打算改用Command來撰寫。畢竟目前在VS2010寫ASP.NET一段時間後我也比較熟悉SqlCommand的寫法。然而卻沒想到會遇到如此特殊的狀況,而原因也完全沒想到會是寫法順序造成的。

 

C#程式碼如下:

 //開啟連線
OleDbConnection oleCon;
oleCon = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\\DATA\\Data.mdb");
oleCon.Open();

//SQL語法
string strSQL = "Update Menu Set Name=@Name Where ID=@ID";
//命令
OleDbCommand cmd = new OleDbCommand(strSQL, oleCon);
//加入參數
cmd.Parameters.AddWithValue("@ID",1);
cmd.Parameters.AddWithValue("@Name", "品項A");

try{
    cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
    MessageBox.Show("發生錯誤!");
}

狀況:執行此段程式碼後不僅資料不會更新,且程式碼也不會跳出錯誤訊息。
原本以為是Where條件寫錯,但是檢查過後發現並不是這原因。
後來經過多方測試並嘗試改寫語句,發現以下寫法Command可以正常執行:

strSQL = "Update Menu Set Name=? Where ID=?";
//加入參數
cmd.Parameters.AddWithValue("?", "品項A");
cmd.Parameters.AddWithValue("?",1);

Parameters加入同樣的值,只不過是改用?來加入,但確實能夠更新到資料。
之後嘗試把參數換回@,不過Parameters改為依照Update語法參數出現的順序去加入,如下:

string strSQL = "Update Menu Set Name=@Name Where ID=@ID";
//加入參數
cmd.Parameters.AddWithValue("@Name", "品項A");
cmd.Parameters.AddWithValue("@ID",1);

如此改寫後也可以正常執行。之後再測試Select, Delete 語法都有相同狀況:參數如果沒照語法中出現順序加入會沒有任何反應。

原因:推測可能OleDbCommand即使是使用@來對應命名參數,但在加入時還是會依照SQL語法中參數出現的順序去做替換,所以才會在執行上沒有報任何錯誤,但是參數位置卻替換錯誤導致Where條件沒有抓到任何筆資料。

結論:確認OleDbCommand在加入Parameters時,都必須按照出現順序去加入才能正常執行。

後話:因為我平常撰寫ASP.NET時考慮到資安的問題,語法中參數習慣用Parameters @來傳入,加上資料庫通常是使用MSSQL,所以大都是使用SqlCommand去和資料庫溝通,但是並沒有發生過此狀況。
     之後測試使用同樣VS2019的版本,且SqlCommand.Parameters沒有配合語法中出現順序去加入,但執行起來也沒有發生問題。看來只在OleDbCommand上才會有這狀況,不知道這算是VS2019的Bug還是OleDbCommand的邏輯本來就是必須照順序去加入參數才行。因此我目前撰寫上只能配合OleDbCommand的狀況,在加入Parameters參數時注意排序。

    


沒有留言:

張貼留言