惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

IT之家
IT之家
The GitHub Blog
The GitHub Blog
F
Fortinet All Blogs
Last Week in AI
Last Week in AI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
L
LangChain Blog
爱范儿
爱范儿
博客园_首页
Stack Overflow Blog
Stack Overflow Blog
MongoDB | Blog
MongoDB | Blog
博客园 - 三生石上(FineUI控件)
大猫的无限游戏
大猫的无限游戏
宝玉的分享
宝玉的分享
GbyAI
GbyAI
H
Help Net Security
A
About on SuperTechFans
Recent Announcements
Recent Announcements
Hugging Face - Blog
Hugging Face - Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
雷峰网
雷峰网
D
Docker
博客园 - Franky
有赞技术团队
有赞技术团队
G
Google Developers Blog

博客园 - 寒带鱼

协程的原理(Coroutine Theory) SQLite数据库学习小结——Frameworks层实现 SQLite数据库学习小结——native层实现 如何用javascript取出session中的值? - 寒带鱼 - 博客园 Session丢失的解决办法小结 返回动态生成的数组的方法 [翻译]编写高性能Web应用程序的10个技巧 [译]30分钟正则表达式指导 操作Word文档的类(VB.NET) MySQL5.0中文手册(13.1. 数据定义声明) ADO.NET对象模型 妹妹生了个女儿,纪念一下 从ASP.NET得到Microsoft Word文档 短期目标 做项目的一点收获之二 2005年中国软件产业最大规模前100家企业名单 关于文件操作的问题 做项目的一点收获之一 数组定义的疑问
连接池泄露了~
寒带鱼 · 2006-06-01 · via 博客园 - 寒带鱼

    做这个项目有近三个月了,在测试网页时总是感觉速度挺慢,但是一直没有发现是哪里的问题。前几天做的一个比较复杂页面中,一个按钮就调用了几次数据访问层的方法,这样反复几次操作之后页面就会崩掉,返回的错误大致是:连接池中的连接已达到最大上限,不能在打开新的连接了。原来是连接池泄露了

    我在数据库访问层中写的方法都是调用MS的SQLHelpe类中提供的方法来直接访问数据库的,其中的ExecuteReader方法如下:

public static SqlDataReader ExecuteReader(string connString, CommandType cmdType, string cmdText, params SqlParameter[] cmdParms) 
        
{
            SqlCommand cmd 
= new SqlCommand();
            SqlConnection conn 
= new SqlConnection(connString);

            
// we use a try/catch here because if the method throws an exception we want to 
            
// close the connection throw code, because no datareader will exist, hence the 
            
// commandBehaviour.CloseConnection will not work
            try 
            
{
                PrepareCommand(cmd, conn, 
null, cmdType, cmdText, cmdParms);
                SqlDataReader rdr 
= cmd.ExecuteReader(CommandBehavior.CloseConnection);
                cmd.Parameters.Clear();
                
return rdr;
            }

            
catch 
            
{
                conn.Close();
                
throw;
            }

        }


    既然有CommandBehavior.CloseConnection了,我想读取完数据连接就应该自动关闭了吧,就没在我的代码里手动关闭,结果反而就是上了这个自动关闭的当了。在William Vaughnm文章里,他说到了连接池泄露的几种可能性:

    “当代码完成 DataReader 后,您要在 SqlConnection 对象停止作用之前关闭 SqlConnection。要处理行集,您可以将 DataReader 传递到应用程序中的另一个例程,但仍然需要确保 DataReader 及其连接处于关闭状态。如果您不关闭 SqlConnection,代码会“泄漏”每个操作的连接,于是连接池对连接进行累积,最后便发生溢出。与 ADO 和 Visual Basic (VB) 6.0 中的情况不同,.NET 垃圾回收器不会为您关闭 SqlConnection 并进行清理。

    “您也可能在使用 DataAdapter 对象时遇到问题。DataAdapter Fill 和 Update 方法可自动打开 DataAdapter 对象的连接,并在数据 I/O 操作完成后关闭该连接。不过,如果该连接在执行 Fill 或 Update 方法时已经处于打开状态,那么,ADO.NET 在方法执行完以后不会关闭 SqlConnection。这是另一个发生连接“泄漏”的机会。”

    既然CommandBehavior.CloseConnection不能够保证在使用完连接后关闭它,那么它有什么用呢?

    “只有当您在 ASP.NET Web 应用程序中使用复杂的绑定控件时,该选项才以这种方式工作。在整个 DataReader 结果集中循环到其行集的末尾(也就是说,当 Dr.Read — DataReader 的 Read 方法 — 返回 False 时)还不足以触发连接的自动关闭。不过,如果您绑定到一个复杂的绑定控件(例如,DataGrid),该控件则会关闭 DataReader 和连接 ”

    在每次使用完SQLHelper返回的DataReader对象之后加上一个手动关闭Reader的语句,在每次使用完SQLHelper的更新数据库操作之后都加上关闭数据库连接的语句,问题得到解决。