[C#]记录一次异常排查,关于using语法、sqlserver数据库session、DBHelper类
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了[C#]记录一次异常排查,关于using语法、sqlserver数据库session、DBHelper类,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3318字,纯文字阅读大概需要5分钟。
内容图文
![[C#]记录一次异常排查,关于using语法、sqlserver数据库session、DBHelper类](/upload/InfoBanner/zyjiaocheng/888/81cfdcae6cc84c92a722a136786adad8.jpg)
最近在做一个基于asp.net和sqlserver的网站项目,发现网站运行一段时间之后,会报异常:
超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小
这异常明显是sqlserver数据库连接池超出了默认大小,估计是代码哪里忘了释放DB链接了。
排查数据访问层代码跟DBHelper,搞了半天解决了。
总结一点东西,记录一下。
DBHelperA代码:
public class DBHelperA { public string connStr = "你的sqlserver数据库连接"; public IDbConnection _conn; public IDbConnection Conn { get { if (_conn == null) { _conn = new SqlConnection(connStr); } return _conn; } } }
ClassA代码:
public class ClassA :DBHelperA { public void DoItFirst() { using (Conn) { if (Conn.State == ConnectionState.Closed) { Conn.Open(); Console.WriteLine(Conn.GetHashCode()); } } } public void DoItSecond() { using (Conn) { if (Conn.State == ConnectionState.Closed) { Conn.Open(); Console.WriteLine(Conn.GetHashCode()); } } } }
创建ClassA对象并调用两个方法:
public static void TestA() { for (int i = 1; i < 200; i++) { ClassA a = new ClassA(); a.DoItFirst(); a.DoItSecond(); Console.WriteLine(i); } Console.ReadLine(); }
以上代码乍一看没啥问题,但是一运行,会在 a.DoItSecond()方法抛出异常:ConnectionString属性未初始化
这是因为,在执行完DoItFirst()方法之后,using语句释放了Conn对象占用的资源,但是Conn对象并不为空
所以在执行DoItSecond()方法时,并不会重新创建Conn对象。导致还用那个已经释放了资源的Conn对象去打开数据库连接,导致异常的发生
DBHelperB代码:
public class DBHelperB { public string connStr = "你的sqlserver数据库连接"; public IDbConnection Conn { get { var conn = new SqlConnection(connStr); Console.WriteLine(conn.GetHashCode()); return conn; } } }
ClassB代码:
public class ClassB :DBHelperB { public void DoIt() { using (Conn) { if (Conn.State == ConnectionState.Closed) { Conn.Open(); Console.WriteLine(Conn.GetHashCode()); } } } }
创建ClassB对象并调用方法:
public static void TestB() { for (int i = 1; i < 200; i++) { ClassB b = new ClassB(); b.DoIt(); Console.WriteLine(i); } Console.ReadLine(); }
执行抛出异常:
此时查看数据库的session连接,发现有100个连接:
这是因为DoIt方法中,每次对Conn对象的引用,都会返回一个新的连接,所以using语句打开和释放的不是同一个conn对象,导致数据库中创建了很多连接
DBHelperC代码:
public class DBHelperC { public string connStr = "你的sqlserver数据库连接"; }
ClassC代码:
public void DoIt() { using (var Conn = new SqlConnection(connStr)) { if (Conn.State == ConnectionState.Closed) { Conn.Open(); Console.WriteLine(Conn.GetHashCode()); } } }
创建ClassC对象并调用方法:
public static void TestC() { for (int i = 1; i < 200; i++) { ClassC c = new ClassC(); c.DoIt(); Console.WriteLine(i); } Console.ReadLine(); }
执行代码,不会报任何异常。且数据库有且只有一个session
因为每次是在using语句块儿里面创建connection对象,using创建和释放的是同一个对象。
另外因为数据库的connectionString没有指定pooling参数,所以默认是启用连接池的。
所以c#代码中connection对象的创建与销毁不会影响sqlserver数据库中的对象。
每次代码创建connection对象,调用open()方法,数据库用的还都是连接池中第一次构建的那个session
现在我把连接字符串的pooling改成false
第一次循环时,数据库session创建时间
第一次循环跳出using语句之后,session没了
第二次循环,又重新创建了新的db session
综上所述:
在构造DBHelper类和数据库访问层的时候,一定要注意connection对象的释放。否则就会导致数据库中一堆的无效session
代码在这儿,有兴趣的可以试一下( 把数据库连接改成你自己的sqlserver数据库地址就可以了):
内容总结
以上是互联网集市为您收集整理的[C#]记录一次异常排查,关于using语法、sqlserver数据库session、DBHelper类全部内容,希望文章能够帮你解决[C#]记录一次异常排查,关于using语法、sqlserver数据库session、DBHelper类所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。