最近在做一个基于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 = ; i < ; 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 = ; i < ; 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 = ; i < ; 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类的更多相关文章

  1. redis 异常排查

    异常排查 redis-server redis.windows.conf D:\redis-2.8.17>redis-server.exe redis.windows.conf[4692] 27 ...

  2. PHP的日志记录-错误与异常记录

    PHP的日志记录-错误与异常记录 提到 Nginx + PHP 服务的错误日志,我们通常能想到的有 Nginx 的 access 日志.error 日志以及 PHP 的 error 日志.虽然看起来是 ...

  3. CPU负载过高异常排查实践与总结

    昨天下午突然收到运维邮件报警,显示数据平台服务器cpu利用率达到了98.94%,而且最近一段时间一直持续在70%以上,看起来像是硬件资源到瓶颈需要扩容了,但仔细思考就会发现咱们的业务系统并不是一个高并 ...

  4. SpringSecurity权限管理系统实战—八、AOP 记录用户、异常日志

    目录 SpringSecurity权限管理系统实战-一.项目简介和开发环境准备 SpringSecurity权限管理系统实战-二.日志.接口文档等实现 SpringSecurity权限管理系统实战-三 ...

  5. 服务器 CPU 100% 异常排查实践与总结

    一个执着于技术的公众号 问题背景 昨天下午突然收到运维邮件报警,显示数据平台服务器cpu利用率达到了98.94%,而且最近一段时间一直持续在70%以上,看起来像是硬件资源到瓶颈需要扩容了,但仔细思考就 ...

  6. sqlserver数据库脱机时发生异常:由于无法在数据库 'SMS' 上放置锁,ALTER DATABASE 失败。请稍后再试。 ALTER DATABASE 语句失败。 (.Net SqlClient Data Provider)

    sqlserver数据库脱机时发生异常,如下: =================================== 设置脱机 对于 数据库“SMS”失败.  (Microsoft.SqlServe ...

  7. jsp连接sqlServer数据库教程、jsp连接sqlServer数据库报ClassNotFoundException异常

    jsp连接sqlServer数据库教程: 首先讲下我用的工具版本以供参考: jar包:jtds1.3.1.jar  下载地址:点击进入 数据库:SQL Server2012 服务器:Tomcat8.0 ...

  8. SQLServer数据库之SQL Server 获取本周,本月,本年等时间内记录

    本文主要向大家介绍了SQLServer数据库之SQL Server 获取本周,本月,本年等时间内记录,通过具体的内容向大家展现,希望对大家学习SQLServer数据库有所帮助. datediff(we ...

  9. 【Redis连接超时】记录线上RedisConnectionFailureException异常排查过程

    项目架构: 部分组件如下: SpringCloudAlibaba(Nacos+Gateway+OpenFeign)+SpringBoot2.x+Redis 问题背景: 最近由于用户量增大,在高峰时期, ...

随机推荐

  1. Unity HOME

    { https://unity.com/cn?_ga=2.134655153.1528856053.1574826116-818341090.1574826116 }

  2. Shiro学习(10)Session管理

    Shiro提供了完整的企业级会话管理功能,不依赖于底层容器(如web容器tomcat),不管JavaSE还是JavaEE环境都可以使用,提供了会话管理.会话事件监听.会话存储/持久化.容器无关的集群. ...

  3. 兼容ie8的多维数组——深拷贝

    浅拷贝只是把对象的内存位置指针给拷贝了,若修改拷贝对象,则原对象也会跟踪修改. var a = {a : 'old', b : { c : 'old'}} var b = Object.assign( ...

  4. VC内联汇编,引用程序中的变量

    int a=5; //变量a _asm { mov eax,a;       //将变量a的值放入寄存器eax add eax,eax;   //相当于a=a+a mov a,eax;      // ...

  5. elipse手机设备显示Target unknown或者offline解决方法

    参考资料: http://blog.csdn.net/yuanjingjiang/article/details/11297433 http://www.educity.cn/wenda/153487 ...

  6. artTemplate性能卓越的 js 模板引擎

    artTemplate-3.0 新一代 javascript 模板引擎 目录 特性 快速上手 模板语法 下载 方法 NodeJS 使用预编译 更新日志 授权协议 特性 性能卓越,执行速度通常是 Mus ...

  7. Haskell语法

    http://www.ibm.com/developerworks/cn/java/j-cb07186.html 1. 构造符号 : 比如: 1:2:3:[] 而常用的 [1,2,3] 是一种语法糖( ...

  8. 剑指offer——73股票的最大利润

    题目: 假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少?例如,一只股票在某些时间节点的价格为{9,11,8,5,7,12,16,14}.如果我们能在价格为5 ...

  9. 并发编程(二)——利用Process类开启进程、僵尸进程、孤儿进程、守护进程、互斥锁、队列与管道

    Process类与开启进程.守护进程.互斥锁 一.multiprocessing模块 1.multiprocessing模块用来开启子进程,并在子进程中执行我们定制的任务(比如函数),该模块与多线程模 ...

  10. centos7下jenkins升级

    systemctl stop jenkins cd cd /usr/lib/jenkins/ mv jenkins.war jenkins.war.bac rz #上传下载好的最新jinkens.wa ...