今天碰到一個很奇怪的問題。
在C#寫的WINFORM程式裡面串連ACCESS資料庫,插入資料庫取最大ID.代碼如下:
1: String strSql = String.Format("INSERT INTO TABLE1 VALUES ()");
2: while (OleDB.ExecuteNonQuery(Program.OfflineDBConnectionString, strSql) != 1)
3: {
4: if (MessageBox.Show("儲存失敗!是否重試?", "提示", MessageBoxButtons.RetryCancel, MessageBoxIcon.Question) != DialogResult.Retry)
5: return 0;
6: }
7: strSql = "SELECT MAX([ID]) AS MAXID FROM TB_BIAOZHU";
8: object oid = OleDB.ExecuteScalar(Program.OfflineDBConnectionString, strSql);
9: int iMaxId = 0;
10: if (oid != DBNull.Value)
11: iMaxId = int.Parse(oid.ToString());
12: return iMaxId;
註:OleDb是自己封閉的一個操作ACCESS的類。
當表是空的時候,如果直接運行,那麼第8行會查詢出一個空值出來,於是返回0 。但很明顯,前面的INSERT是會執行成功才會執行到這裡來,如果用單步運行模式,那麼會一切正常的運行成功。這真的是很奇怪的事情。
在第8行之前加入一句休眠1S的語句後,一切就正常了。但是很疑惑為什麼會這樣,明明已經插入成功了,為什麼查詢不出最大的ID來呢?難道是用的ACCESS資料庫版本或者JETDB引擎的版本有問題?最後沒有辦法,只好在第8句運行返回DBNULL的時候休眠1秒後重新執行查詢語句來解決。如下:
8: object oid = OleDB.ExecuteScalar(Program.OfflineDBConnectionString, strSql);
9: if (oid == DBNull.Value)
10: {
11: System.Threading.Thread.Sleep(1000);
12: oid = OleDB.ExecuteScalar(Program.OfflineDBConnectionString, strSql);
13: }
雖然問題用很不爽的方式解決了,但還是希望弄明白為什麼。
二○○九年六月二十六日 23時40分:最新進展.總算弄明白為什麼了。原來我原先的語句是分兩次執行SQL語句。也就是分別對資料庫建立了一次串連。
當我把兩個語句(INSERT和SELECT)放在一個串連裡執行之後,一切就正常了。
因為ACCESS不支援多條語句放在一起執行,必須在代碼裡面依次執行。所以只好自己又寫了一個方法,傳入一個SQL語句的數組,然後遍曆每個元素放在同一個OleDbCommand裡面執行。代碼如下:
1:
2: /// <summary>
3: /// 實際類似於預存程序的方案。依次執行數組中的語句。最後一條語句使用ExecuteScalar傳回值。
4: /// </summary>
5: /// <param name="strConnectionString"></param>
6: /// <param name="strSqls"></param>
7: /// <returns></returns>
8: public static object ExecuteScalar(String strConnectionString, String[] strSqls)
9: {
10: OleDbConnection Oleconn = new OleDbConnection(strConnectionString);
11: OleDbCommand cmd = new OleDbCommand();
12: cmd.Connection = Oleconn;
13: try
14: {
15: Oleconn.Open();
16: int i = 0;
17: foreach (String strSql in strSqls)
18: {
19: cmd.CommandText = strSql;
20: if (i < strSqls.Length - 1)
21: cmd.ExecuteNonQuery();
22: else
23: {
24: return cmd.ExecuteScalar();
25: }
26: i++;
27: }
28: //永遠不會執行到的語句。
29: return null;
30: }
31: catch
32: {
33: return null;
34: }
35: finally
36: {
37: if (Oleconn.State == ConnectionState.Open)
38: Oleconn.Close();
39: }
40: }