Ado.Net数据库连接池

数据库连接池默认配置

Ado.Net本身就带有数据库连接池,使用Ado.Net进行数据库连接操作时,默认开启数据库连接池。连接池的行为可以通过连接字符串来控制,主要包括四个重要的属性。

  • Connection Timeout:连接请求等待超时时间。默认为15秒。
  • Max Pool Size:连接池中最大连接数,默认为100.
  • Min Pool Size:连接池中最小连接数,默认为0.
  • Pooling:是否启用连接池。默认启用连接池。需要禁用时,手动设置Pooling=false。

数据库连接池工作原理

连接池是区分不同类别的。也就是说,同一时刻同一应用程序域可以有多个不同类型的连接池。连接池是如何标识区分不同类别的呢?细致来讲,连接池是由进程、应用程序域、连接字符串以及Windows标识共同组成签名来标识区分的。
但对于同一应用程序域来说,一般只由连接字符串来区分。当打开一条连接时,如果该条连接的签名与现有的连接池类型不匹配,则创建一个新的连接池。反之,则不创建新的连接池。

 using (SqlConnection conn1 = new SqlConnection("Data Source=LENOVO-PC\\MR2014;" +
                "Initial Catalog = Mytest;User Id = sa;Password = ;"))
            {
                conn1.Open();
                MessageBox.Show(conn1.State.ToString());
            }
            using (SqlConnection conn2 = new SqlConnection("Data Source=LENOVO-PC\\MR2014;" +
                "Initial Catalog = MyCar;User Id = sa;Password = ;"))
            {
                conn2.Open();
                MessageBox.Show(conn2.State.ToString());
            }
            using (SqlConnection conn3 = new SqlConnection("Data Source=LENOVO-PC\\MR2014;" +
                "Initial Catalog = Mytest;User Id = sa;Password = ;"))
            {
                conn3.Open();
                MessageBox.Show(conn3.State.ToString());
            }

上面实例中,创建了三个数据库连接,但由于conn1和conn3的连接字符串相同,所以共享了一个连接池。因此管理时只需要两个连接池。打开第二个连接,该条连接的签名与现有的连接池不匹配,因此创建一条新的连接。

当用户创建连接请求或者说调用Connection对象的Open时,连接池管理器首先要根据连接请求的类型签名找到匹配的连接池,然后尽力分配一条空闲的连接。具体情况如下:

  • 如果池中有空闲连接可用,返回该连接;
  • 如果池中连接都已用完,创建一个新连接添加到池中;
  • 如果池中连接已达到最大连接数,请求进入等待队列直到有空闲连接可用。

无效连接,即不能正确连接到数据库服务器的连接。连接池存储的与数据库服务器的连接数量是有限的。因此,如果不及时移除无效连接,将会浪费连接池的空间。连接池管理器如果检测到与服务器的连接已断开,或者连接长时间空闲,连接池管理器会将该连接移除。

当我们使用完一条连接时,应当及时关闭连接和释放连接,以便连接可以返回连接池中重复使用。我们可以通过Connection对象的Close方法和Dispose方法来关闭和释放连接,也可以通过C#的using语句来关闭连接。

配置代码

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


namespace 数据库连接池测试
{
    class Conn
    {
        private SqlConnection m_sqlConnection;
        public Conn()
        {
            m_sqlConnection = new SqlConnection(GetStrSql());
        }
        // 构造连接池字符串
        private string GetStrSql()
        {
            // pooling:用来设置是否开启连接池,默认为true
            // connection lifetime:设置连接池的生命周期,默认为0
            // min pool size:线程池的最小连接数
            // max pool size:线程池的最大连接数
            // Data Source:服务器地址(Server)
            // Initial Catalog:数据库(database)
            // User ID:用户ID(uid)
            // Password:密码(pwd)
            //return "pooling=true;connection lifetime=5;min pool size = 2;max pool size=4; Data Source = 127.0.0.1; Initial Catalog = tempdb; User ID = sa; Password=123456";
            // AsynchronousProcessing 设置异步访问数据库
            // ConnectTimeout 设置连接等待时间
            return "server=localhost\\MSSQL;integrated security=sspi;database=Test;Max Pool Size=100;Min Pool Size=2;Connect Timeout=5;Connection Lifetime=300;Pooling=true;Asynchronous Processing=true";
        }
        public DataTable GetDataReader(string a_StrSql)//数据查询,连接池接口
        {
            // 判断数据库的状态
            if (m_sqlConnection.State == ConnectionState.Open)
            {
                m_sqlConnection.Close();  // 关闭
            }
            try
            {
                m_sqlConnection.Open();
                SqlCommand l_sqlCommand = new SqlCommand(a_StrSql, m_sqlConnection);
                SqlDataReader l_sqldatareader = l_sqlCommand.ExecuteReader();
                if (l_sqldatareader.HasRows)
                {
                    DataTable l_dt = new DataTable();            // 如果想使用相同的字符串来访问不同的数据库,可以使用改变数据库:m_sqlconnection.ChangeDatabase(数据库名称);
                    l_dt.Load(l_sqldatareader);
                    l_sqldatareader.Close();
                    m_sqlConnection.Close();
                    return l_dt;
                }
                return null;
            }
            catch (Exception err)
            {
                Console.Write(err.Message);
                return null;
            }
            finally
            {
                m_sqlConnection.Close();
            }
        }
    }
}

高效使用连接池的基本原则

用好连接池将会大大提高应用程序的性能。相反如果使用不当,则百害而无一利。一般来说,使用连接池遵循以下原则:

  • 在最晚的时刻申请连接,最早的时候释放连接
  • 关闭连接时先关闭相关用户定义的事务
  • 确保并维持连接池中至少有一个打开的连接
  • 尽量避免池碎片的产生。主要包括集成安全性产生的池碎片以及使用许多数据库产生的池碎片

参考链接

ADO.NET入门教程(五) 细说数据库连接池
SQL Server 连接池 (ADO.NET)

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。