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)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343