天天看點

【輕松一刻!】一段難倒了兩名老程式猿的簡單代碼

▄︻┻┳═一「static」Agenda:

▄︻┻┳═一​​static,你還敢用嗎?​​

▄︻┻┳═一​​static,你還敢用嗎?(二)​​

▄︻┻┳═一​​【輕松一刻!】一段難倒了兩名老程式猿的簡單代碼​​

昨天的代碼改完之後,再次部署服務。今天檢查日志卻發現了新的bug——程式頻報如下異常:

生成賬單時異常:System.InvalidOperationException: The connection is not open.      

根據異常堆棧資訊定位到dal層方法:

public static bool Add(t_bills entity)      

先貼出來相關代碼吧:

1 public class BillsDal
 2 {
 3     static IDbConnection _conn /*= ConnUtility.GateWayConntion;*/
 4     {
 5         get { return ConnUtility.GateWayConntion; }
 6     }
 7     static object syncRoot = new object();
 8 
 9     /// <summary>
10     /// 插入記錄(啟用事務來處理主鍵BillId)
11     /// </summary>
12     /// <param name="entity"></param>
13     /// <returns></returns>
14     public static bool Add(t_bills entity)
15     {
16         if (entity.CreatedTime == DateTime.MinValue)
17         {
18             entity.CreatedTime = DateTime.Now;
19         }
20 
21         lock (syncRoot)
22         {
23             IDbConnection _conn = ConnUtility.GateWayConntion;
24             _conn.Open();
25             var trans = _conn.BeginTransaction();
26             try
27             {
28                 var maxId = _conn.ExecuteScalar<long?>("SELECT MAX(BillId) FROM T_Bills;");
29                 if (maxId == null || maxId < CommonBase.BillId_DefaultValue)
30                 {
31                     maxId = CommonBase.BillId_DefaultValue;
32                 }
33                 entity.BillId = maxId.Value + 1;
34 
35                 long i = _conn.Insert<long>(entity, trans);
36                 trans.Commit();
37                 i = 1; //執行Insert傳回值是0,這裡給1,以供下面的判斷
38                 return i > 0;
39             }
40             catch
41             {
42                 trans.Rollback();
43                 throw;
44             }
45             finally
46             {
47                 _conn.Close();
48             }
49         }
50     }
51      

經調試程式,發現執行var trans = _conn.BeginTransaction();這句時,報出了上面的異常:The connection is not open.

奇怪!前面一行代碼是_conn.Open();呀,既然已經把連接配接打開了,怎麼這裡卻提示“連接配接已關閉”呢?

我問旁邊的同僚,一個老程式猿,我跟他講了昨天改動的原委,說_conn原來是這麼定義的static IDbConnection _conn = ConnUtility.GateWayConntion;,後來改成了隻讀屬性,即static IDbConnection _conn{get { return ConnUtility.GateWayConntion; }},執行這個Add方法就出現這個異常了。

我倆分析這段代碼,你一言我一嘴的,讨論了有20分鐘。

後來,

BTW,你看出來原因了嗎?

後來,原因竟然是這個。。。

後來我的眼睛落在了var trans = _conn.BeginTransaction();的_conn上,猛然發現,是因為_conn.Open();裡的IDbConnection執行個體與var trans = _conn.BeginTransaction();裡的IDbConnection執行個體不是一個執行個體,因為每次調用隻讀屬性拿到的都是一個新的執行個體。 然後。。。

然後,我給你講個故事吧? 這個故事你可能聽說過,也可能沒聽說過。