【.Net】使用Dapper时真的需要管理数据库连接吗?

一、背景:

最近在开发过程中遇到一个问题,项目上线后几分钟后就会报错”数据库连接池已满、连接超时”,项目就宕掉了。后来细心的同事发现了可疑的点,操作数据库后没有将连接Close,也没有using连接对象,经过简单的修改后果然问题解决了。

异常如下:

Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.


二、原因:

在不关闭数据库连接的情况下,即便数据库已经返回了操作结果,但连接一直处于占用中没有断开,当操作数次后(Sql Server默认最大100个连接)连接就被全部占满,后续的连接请求会先等待前面占用的连接释放,直到成功建立连接或建立连接超时。


三、探索:

由于我们这个项目使用的ORM框架是Dapper,而我的印象中使用Dapper几乎是不需要我们手动调用的Open()、Close()方法的,自己之前开发的项目运行多年也并没有出现过这个问题,那究竟问题出现在了哪一个环节?

版本bug?不是,无论是更新或是降级问题依然存在!

难道这么多年真是我用错了,没有报错只是巧合?

翻翻官方给出的案例并也并没有发现关于Open()、Close()方法的调用。

1.先来撸代码实际测试一下:

测试发现执行Query<T>方法即使不执行Open()依然可以查询到结果,并且并不影响后续的查询操作,而操作完成后数据库状态处于Closed状态,说明Dapper其内部在进行操作前会自行Open(),操作完成后会自行Close()。经测试正常情况下Execute()方法也并不需要Open()、Close(),且操作也能执行成功。

注:后面将介绍什么情况下需要调用Open()、Close()。

2.那我们在来试一下Open()后的效果:

当Open()后在执行Query<T>方法,执行结束后连接并不会自动关闭!!!

难道这就是导致此次事故的罪魁祸首?翻翻代码,在项目底层封装中,有这样一行代码,果然就是它!!!

经过实际测试发现,处于Closed状态的连接Dapper执行后会自动关闭,而处于Open状态下的连接Dapper执行后需要我们自己来Close。当然,这只是从结果推导出来的结论,那Dapper实际执行中真的是这样吗?

3.接下来就让我们翻翻源码一探究竟吧!

Dapper最核心的代码都在SqlMapper类中,而Query<T>相关方法在其内部都调用的是一个QueryImpl<T>方法。

在我们调用Query<T>方法时Dapper将sql及参数事务等保存到CommandDefinition对象中传递给QueryImpl<T>方法,之后由command.SetupCommand()方法生成IDbCommand对象,再由ExecuteReaderWithFlagsFallback方法执行数据库操作,生成IDataReader的对象。这里有很重要的几行代码如下图(图片太长,省略了部分与本文无关的代码)。

1082行,当连接处于关闭状态时(新连接初始状态,调用Close()方法后也是这个状态)将其打开。

1083行,执行数据库操作,用IDataReader来存储结果。

1084行,连接状态标志位wasClosed置为false

1124行,当wasClosed值为true时关闭连接。

这就很奇怪了,当1084行执行后1124行一定不会被执行,而1124行什么情况下才会被执行呢?既然不是1124行执行的Close(),那到底是谁把连接关闭了呢?

带着这两个疑问,我们继续往下看:

先来说1124行的执行条件,1083行执行成功,1083行执行报错,1084行未被执行,抛出异常被try-finally捕获,此时wasClosed值为true,1124行执行成功,数据库连接关闭。

再来说另一点,答案就藏在1083行的ExecuteReaderWithFlagsFallback方法中,我们看到wasClosed被传递到了这个方法中,那在这个函数内部用它来干什么了呢?


ExecuteReaderWithFlagsFallback中将wasClosed参数传递给了GetBehavior方法,继续往下看。

发现个可疑点CommandBehavior.CloseConnection,看看他是干嘛的,“关闭DataReader对象时,关联的Connection对象也会关闭”,就是他了!!!QueryImpl<T>方法使用的就是DataReader对象来取数据的,执行完毕后第1108行reader.Dispose()将其释放,Connection对象也就随之关闭了!!!

经过阅读、编译、调试源码后发现结论与推断相同。其他查询操作的内部实现原理与此类似,而Execute<T>等的逻辑就比较简单了,这里就不再过多解释了。

4.什么情况下需要我们自己管理连接状态?

事务!通过报错可以看到,创建事务时连接必须处于Open状态。而事务执行完毕后一定要记得Close() !!!

连续操作数据库不执行业务逻辑时也算是一种情况,但也有可能在高并发、数据量大的情况下造成连接池占满的情况,这种情况就留给大家自行测试吧。


四、结论

在使用Dapper时不需要管理连接状态,只有在执行事务时才需要去管理,开启事务前要Open(),事务后要Close(),切记!切记!切记!!!

注:为什么不直接将连接using掉?这个要综合的去分析,跟数据库连接池也有关,看编程的写法,看具体的业务,不在本文的重点范围内。




此账号不定期分享一些开发过程中踩过的坑以及解决方案,希望对您有所帮助。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,245评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,749评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,960评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,575评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,668评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,670评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,664评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,422评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,864评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,178评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,340评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,015评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,646评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,265评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,494评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,261评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,206评论 2 352

推荐阅读更多精彩内容