ACCESS插入数据得到自增ID的问题
今天碰到一个很奇怪的问题。
在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: }