天天看点

【轻松一刻!】一段难倒了两名老程序猿的简单代码

▄︻┻┳═一「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实例不是一个实例,因为每次调用只读属性拿到的都是一个新的实例。 然后。。。

然后,我给你讲个故事吧? 这个故事你可能听说过,也可能没听说过。