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

昨天的代码改完之后,再次部署服务。今天检查日志却发现了新的bug——程序频报如下异常:

生成账单时异常:System.InvalidOperationException: The connection is not open.#

根据异常堆栈信息定位到dal层方法:

public static bool Add(t_bills entity)

先贴出来相关代码吧:

public class BillsDal
{
    static IDbConnection _conn /*= ConnUtility.GateWayConntion;*/
    {
        get { return ConnUtility.GateWayConntion; }
    }
    static object syncRoot = new object();

    /// <summary>
    /// 插入记录(启用事务来处理主键BillId)
    /// </summary>
    /// <param name="entity"></param>
    /// <returns></returns>
    public static bool Add(t_bills entity)
    {
        if (entity.CreatedTime == DateTime.MinValue)
        {
            entity.CreatedTime = DateTime.Now;
        }

        lock (syncRoot)
        {
            IDbConnection _conn = ConnUtility.GateWayConntion;
            _conn.Open();
            var trans = _conn.BeginTransaction();
            try
            {
                var maxId = _conn.ExecuteScalar<long?>("SELECT MAX(BillId) FROM T_Bills;");
                if (maxId == null || maxId < CommonBase.BillId_DefaultValue)
                {
                    maxId = CommonBase.BillId_DefaultValue;
                }
                entity.BillId = maxId.Value + 1;

                long i = _conn.Insert<long>(entity, trans);
                trans.Commit();
                i = 1; //执行Insert返回值是0,这里给1,以供下面的判断
                return i > 0;
            }
            catch
            {
                trans.Rollback();
                throw;
            }
            finally
            {
                _conn.Close();
            }
        }
    }
}

经调试程序,发现执行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();里的_conn实例和var trans = _conn.BeginTransaction();里的_conn实例不是一个实例,因为每次调用只读属性拿到的都是一个新的实例。 然后。。。

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

......

故事是:从前,有个人为了寻觅一种野草药,每天从山脚下爬到山上,苦苦寻觅,早出晚归。后来,他意外的发现,他所苦苦寻觅的野草药,就在他每日经过的山脚下。

【轻松一刻!】一段难倒了两名老程序猿的简单代码
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,780评论 18 399
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,026评论 19 139
  • 一. Java基础部分.................................................
    wy_sure阅读 3,840评论 0 11
  • 阳光好得不得了,花儿争相绽放,在阳光下,像是一颗颗星星,明媚耀眼。 杏花尤其好看,枝干色黑而虬曲,花朵却娇嫩柔软,...
    青青苔阅读 674评论 0 4
  • 1 妞妞是十一点之后,谁也不能阻止她和周公约会的人,那是她雷打不动遵循的美容觉时间。 平常周末放假,约她唱K泡吧,...
    猫佑530阅读 286评论 0 2