▄︻┻┳═一「static」Agenda:

▄︻┻┳═一static,你还敢用吗?

▄︻┻┳═一static,你还敢用吗?(二)

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


为了压系统,昨天小组在测试环境模拟了一大批订单数据。今天上午查看记录的账单计息日志,发现了一大堆的MySqlException

MySql.Data.MySqlClient.MySqlException (0x80004005): There is already an open DataReader associated with this Connection which must be closed first.

诸如:

2017-01-05 00:40:49.891
账单计息异常/{"BillId":1000012082,"OrderId":"DD201701040002672"}:MySql.Data.MySqlClient.MySqlException (0x80004005): There is already an open DataReader associated with this Connection which must be closed first.
在 MySql.Data.MySqlClient.ExceptionInterceptor.Throw(Exception exception)
在 MySql.Data.MySqlClient.MySqlCommand.Throw(Exception ex)
在 MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior)
在 MySql.Data.MySqlClient.MySqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
在 System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior)
在 CommonLibrary.CommonOrm.CommonOrm_Dapper.<QueryImpl>d__11`1.MoveNext() 位置 e:\work\yijia\trunk\CommonLibrary\CommonOrm\CommonOrm_Dapper.cs:行号 1554
在 System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
在 System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
在 CommonLibrary.CommonOrm.CommonOrm_Dapper.Query[T](IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Boolean buffered, Nullable`1 commandTimeout, Nullable`1 commandType) 位置 e:\work\yijia\trunk\CommonLibrary\CommonOrm\CommonOrm_Dapper.cs:行号 1444
在 GateWay.DAL.BillsDal.BillsDal.GetOrdersBillList(String bizOrderId) 位置 e:\work\yijia\trunk\GetWay.DAL\BillsDal\BillsDal.cs:行号 123
在 GateWay.BLL.Bills.BillsBll.GetOrdersBill(String bizOrderId, BillTypeEnum billType) 位置 e:\work\yijia\trunk\GetWay.BLL\Bills\BillsBll.cs:行号 27
在 GateWay.BLL.Bills.PrincipalBillsInterest.InterestBill(t_bills principleBill) 位置 e:\work\yijia\trunk\GetWay.BLL\Bills\PrincipalBillsInterest.cs:行号 186
在 GateWay.BLL.Bills.PrincipalBillsInterest.Interest() 位置 e:\work\yijia\trunk\GetWay.BLL\Bills\PrincipalBillsInterest.cs:行号 77

通过分析程序,发现dal层的所有方法都是静态的,其中还包括一个静态的db连接对象:

public class BillsDal
{
static IDbConnection _conn = ConnUtility.GateWayConntion; /// <summary>
/// 获取指定业务订单的所有账单(by 商户code和订单号)
/// </summary>
/// <param name="bizOrderId">订单Id,唯一</param>
/// <returns></returns>
public static List<t_bills> GetOrdersBillList(string merCode, string bizOrderNo)
{
var obj = _conn.Query<t_bills>("select * from t_bills where merCode='" + merCode + "' and orderNo='" + bizOrderNo + "'");
return obj.ToList();
}
}

突然想到之前整理的blog《static,你还敢用吗?》,所以,不难分析出来原因:问题就出在这个静态的db连接对象_conn上,因为所有类的实例始终是用一个db连接,当并发出现时,又没有lock数据操作代码,那么,就很容易出现连接在未关闭时又要被建立并打开,这样就出现了db连接异常。

经模拟多线程来测试,的确如此。

问题即答案!修复这个bug的话,有如下2个方案:

  1. 如果仍然要保留这个static的_conn字段,就要用lock来锁住数据操作代码(GetOrdersBillList),以控制并发冲突
  2. 每次查询时用一个新的连接对象。

方案分析:第1种,涉及到对象只能在被释放(关闭)掉才能再次被使用(打开),性能低下,不可取。 第2种呢,其实在dal层,绝大多数的程序猿都是按照每一个数据操作只用一个db连接的方式来编码的。 由于大家一般不会把dal类的成员定义成static,所以,也就不会遇到这样的db连接异常。而我呢,倾向于用static方法,考虑到封装,就把这个db连接对象封装成静态字段了,反而忽视了静态数据成员带来的隐患——数据量小时几乎是暴露不出来问题,一旦数据量大起来,有了并发,就会出现资源被同时使用,这样的话,多个线程实例都要修改其状态时,就出现了并发异常。

由此来看,依然用static的话,就要把_conn当做只读的私有属性(不考虑代码味道):

    static IDbConnection _conn
{
get { return ConnUtility.GateWayConntion; }
}

这样,当每次访问这个属性时,都会返回一个新的连接对象。

再次模拟多线程测试,ok!

static,你还敢用吗?(二)的更多相关文章

  1. PHP之static静态变量详解(二)

    在看别人项目过程中,看到函数里面很多static修饰的变量,关于static修饰的变量,作用域,用法越看越困惑,所以查了下资料. static用法如下: 1.static 放在函数内部修饰变量 2.s ...

  2. 面向对象程序设计-C++ Type conversion (Static) & Inheritance & Composition【第十二次上课笔记】

    这节课继续讲解了 static 作为静态数据成员 / 成员函数的用法 具体详解我都已注释出来了,大家可以慢慢看 有任何问题都可以在这篇文章下留言我会及时解答 :) //static 静态数据成员 // ...

  3. java static成员变量方法和非static成员变量方法的区别 ( 二 )

    原创文章,未经作者允许,禁止转载!!! 静态成员变量不用new对象,在类加载的过程中就已经初始化存放在数据区域,静态成员变量是类和所有对象共有的,类和对象都可以改变它的值,每一次改变值之后,静态成员变 ...

  4. (转)Java中的static关键字解析

    转载: http://www.cnblogs.com/dolphin0520/p/3799052.html 一.static关键字的用途 在<Java编程思想>P86页有这样一段话: &q ...

  5. Java中的static关键字解析

    Java中的static关键字解析 static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一.下面就先讲述一下static关键 ...

  6. (转)Java中的static关键字解析

    转自http://www.cnblogs.com/dolphin0520/p/3799052.html 一.static关键字的用途 在<Java编程思想>P86页有这样一段话: “sta ...

  7. java中的static详解

    如果一个类成员被声明为static,它就能够在类的任何对象创建之前被访问,而不必引用任何对象.static 成员的最常见的例子是main( ) .因为在程序开始执行时必须调用main() ,所以它被声 ...

  8. Java中的static关键字解析 转载

    原文链接:http://www.cnblogs.com/dolphin0520/p/3799052.html Java中的static关键字解析 static关键字是很多朋友在编写代码和阅读代码时碰到 ...

  9. C# 生成二维码,彩色二维码,带有Logo的二维码及普通条形码

    每次写博客,第一句话都是这样的:程序员很苦逼,除了会写程序,还得会写博客!当然,希望将来的一天,某位老板看到此博客,给你的程序员职工加点薪资吧!因为程序员的世界除了苦逼就是沉默.我眼中的程序员大多都不 ...

  10. android 二维码扫描

    了解二维码这个东西还是从微信 中,当时微信推出二维码扫描功能,自己感觉挺新颖的,从一张图片中扫一下竟然能直接加好友,不可思议啊,那时候还不了解二维码,呵呵,然后做项目的时候, 老板说要加上二维码扫描功 ...

随机推荐

  1. bootstrap + requireJS+ director+ knockout + web API = 一个时髦的单页程序

    也许单页程序(Single Page Application)并不是什么时髦的玩意,像Gmail在很早之前就已经在使用这种模式.通常的说法是它通过避免页面刷新大大提高了网站的响应性,像操作桌面应用程序 ...

  2. C语言 · 整数平均值

    编写函数,求包含n个元素的整数数组中元素的平均值.要求在函数内部使用指针操纵数组元素,其中n个整数从键盘输入,输出为其平均值. 样例输入: (输入格式说明:5为输入数据的个数,3 4 0 0 2 是以 ...

  3. SQL Server 无法连接到服务器。SQL Server 复制需要有实际的服务器名称才能连接到服务器。请指定实际的服务器名称。

    异常处理汇总-数据库系列  http://www.cnblogs.com/dunitian/p/4522990.html SQL性能优化汇总篇:http://www.cnblogs.com/dunit ...

  4. HTML5 input元素新的特性

    在HTML5中,<input>元素增加了许多新的属性.方法及控件.本文章分别对这三方面进行介绍. 目录 1. 属性 2. 方法 3. 新控件 1. 属性 <input>元素在H ...

  5. Spring之旅

    Java使得以模块化构建复杂应用系统成为可能,它为Applet而来,但为组件化而留. Spring是一个开源的框架,最早由Rod Johnson创建.Spring是为了解决企业级应用开发的复杂性而创建 ...

  6. Word/Excel 在线预览

    前言 近日项目中做到一个功能,需要上传附件后能够在线预览.之前也没做过这类似的,于是乎就查找了相关资料,.net实现Office文件预览大概有这几种方式: ① 使用Microsoft的Office组件 ...

  7. 23种设计模式--责任链模式-Chain of Responsibility Pattern

    一.责任链模式的介绍 责任链模式用简单点的话来说,将责任一步一步传下去,这就是责任,想到这个我们可以相当击鼓传花,这个是为了方便记忆,另外就是我们在项目中经常用到的审批流程等这一类的场景时我们就可以考 ...

  8. css居中div的几种常用方法

    在开发过程中,很多需求需要我们居中一个div,比如html文档流当中的一块div,比如弹出层内容部分这种脱离了文档流等.不同的情况有不同的居中方式,接下来就分享下一下几种常用的居中方式. 1.text ...

  9. jq选择器基础

    Jquery $代表选择器 使用jq必须要导入jq文件 <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js&qu ...

  10. iOS 数据存储之SQLite3的使用

    SQLite3是iOS内嵌的数据库,SQLite3在存储和检索大量数据方面非常有效,它使得不必将每个对象都加到内存中.还能够对数据进行负责的聚合,与使用对象执行这些操作相比,获得结果的速度更快. SQ ...