ADO.NET 数据库对象池原理/链接池

本文主要是介绍底层原理,单纯的使用可以不看这文章,毕竟ORM也是用的底层的ADO,知道些原理心理更加安心一些

1、ADO.NET 连接池

如何启用和禁用连接池?

答:连接字符串中将连接池值 Pooling 设置为 true 或 yes,则会启用连接池(默认启用)。

启用后连接池后系统会根据并发情况将连接池保持在一个合理区间,让性能最大化,并不会立马清空

而是将他状态更改为sleep。禁用连接池性能会差一些,open就打开连接池 close就关闭连接池

1.1 Open() 

1、启用连接池情况(默认)

先找有没有睡眠的连接池有恢复连接池,如果没有睡眠的连接池打开新的连接池

2、禁用连接池情况(需要字符串关闭)

打开新连接池

1.2 Close ()

1、启用连接池情况(默认)

将现有连接池睡眠

2、禁用连接池情况(需要字符串关闭)

关闭连接池

1.3 dispose()

方法实际是和close()做的同一件事,唯一区别是 dispose会销毁当前C#对象

SqlSugar dispose后在打开不会报错,原理如下

  var db = GetInstance();
  db.Open();
  Console.WriteLine(db.Ado.Connection.GetHashCode());
  db.Close();
  Console.WriteLine(db.Ado.Connection.GetHashCode());
  db.Dispose();
  //如果下次在使用db会new出新的SqlConnection和Ado.net不一样Ado.net是直接报错
  Console.WriteLine(db.Ado.Connection.GetHashCode());

输出结果如下:

image.png

唯一的区别是Dispose后在使用db,db对象会换成新的而不在是以前的,而close后在使用还是同一个db对象

2、SqlConnection和连接池

SqlConnection非线程安全对象,不同上下文要new不同对象

con.Open(); //请求数据库连接池 查找有没有 sleep 状态的,没有创建连接池
con.Close();//将当前连接池状态改为sleep , 如果长时间不用会销毁

上面的原理可以看出

1. 同一个对象多次open 和 close 都是在现有的连接池里面去操作

2. 就算是多个SqlConnection不在同时间请求,也可能会用同一个连接池 

3.多个SqlConnection并发操作会找有没有空闲的连接池,没有在创建

所以连接池在.NET中 微软封装的很好,很成熟 多数.NET用户都不知道是什么玩意儿

连接超时设置

在连接池符串加上 Connection Timeout=10  ,默认是30秒,单位秒

.NET中要配置连接池吗?

 答:什么都不用配置只要学会 open和close就行了 

3、SqlSugarClient原理

1.手动释放模式和SqlConnection原理一模一样,底层就是用的SqlConnection并且需要注意线程安全

//创建数据库对象 SqlSugarClient   
 SqlSugarClient db = new SqlSugarClient(new ConnectionConfig()
 {
            ConnectionString = "Server=.xxxxx", 
            DbType = DbType.SqlServer,
            IsAutoCloseConnection = false//手动释放  是长连接 
 });
 //需要手动using 
 //或者
 //db.Open();
 //db.Close();


2.自动释放(推荐),说白了不需要你去写using或者 close和open

//创建数据库对象 SqlSugarClient   
 SqlSugarClient db = new SqlSugarClient(new ConnectionConfig()
 {
            ConnectionString = "Server=.xxxxx", 
            DbType = DbType.SqlServer,
            IsAutoCloseConnection = true//自动释放
 });
 //写代码就不需要考虑 open close 直接用就行了

 情况1:没有事务的情况 ,每次操作自动调用 open和close

 情况2: 有事务的情况下 ,开启事务调用 open  提交或者回滚事务调用 close

4、SqlSugarScope原理

它是对SqlSugarClient的封装让他支持线程安全,并且在不同上下文自动new 出 SqlSugarClient,在编写代码的时候不需要考虑他线程是否安全

什么是上下文?

异步情况: 在同一串await 中是一个上下文

同步情况: 在同一个线程是同一个上下文

同一个SqlSugarScope做到了在同一个上下文共享一个对象,不同上下文自动去NEW

5、如何验证是否释放

默认情况下只要超过100个请求没关闭就会报错,不同库可能有差异

         for (int i = 0; i < 501; i++)
         {
                SqlSugarClient db = new SqlSugarClient(new ConnectionConfig()
                {
                    DbType = DbType.Oracle,
                    ConnectionString = Config.ConnectionString,
                    IsAutoCloseConnection = false//设成关闭这个代码会直接报错
                });

                db.Ado.GetInt("SELECT 1 from dual"); 
           }
 //IsAutoCloseConnection=true 执行成功
 //IsAutoCloseConnection=false 会出现连接池超时或者超过上限等错误

7、总结

他们3者的关系应该是这样的:

SqlSugarScope 底层+自动释放+上下文安全

SqlSugarClient  底层+自动释放控制

SqlConnection   底层

关闭
果糖网