1、启用了连接池:
默认情况下ADO.Net启用了连接池《连接池占用本地资源,不是数据库服务器资源,只是当连接池有对象是,数据库服务器要一直打开与相应对象的连接【比如本地连接池中有四个连接对象,那么数据库要打开四个连接保持与本地连接对象的连接】》。
连接池的缺点就是始终保持与数据库的连接,本地连接池可以设置大小,用于限制连接池中可以存放连接对象的数量。
1 static void Main(string[] args) 2 { 3 //1.启用连接池与禁用连接池为什么性能差距这么大? 4 //1.当启用连接池后,看似是2000次的登录与注销(连接的打开与关闭),其实只有一次打开,(当程序关闭后才会关闭)。所以高性能 5 6 //2.而禁用连接池后,则是真正的打开关闭了2000次。 7 8 #region 启用连接池 9 10 string constr = "Data Source=zxtiger;Initial Catalog=itcastcn;Integrated Security=True"; 11 12 Stopwatch watch = new Stopwatch(); 13 watch.Start(); 14 //执行2000次打开关闭时间---》00:00:00.1383385 15 for (int i = 0; i < 2000; i++) 16 { 17 using (SqlConnection con = new SqlConnection(constr)) 18 { 19 con.Open(); 20 con.Close(); 21 } 22 } 23 watch.Stop(); 24 Console.WriteLine(watch.Elapsed); 25 26 Console.WriteLine("连接打开了又关闭了。"); 27 Console.ReadKey(); 28 #endregion 29 30 } 31 }
2、禁用连接池:
1 static void Main(string[] args) 2 { 3 //1.启用连接池与禁用连接池为什么性能差距这么大? 4 //1.当启用连接池后,看似是2000次的登录与注销(连接的打开与关闭),其实只有一次打开,(当程序关闭后才会关闭)。所以高性能 5 6 //2.而禁用连接池后,则是真正的打开关闭了2000次。 7 //可以使用SQL SERVER 提供的工具SQL Profiler监测连接情况 8 9 10 #region 禁用连接池后的效果 11 12 string constr = "Data Source=zxtiger;Initial Catalog=itcastcn;Integrated Security=True;Pooling=false"; 13 14 Stopwatch watch = new Stopwatch(); 15 watch.Start(); 16 17 ////禁用连接池执行2000次用时--》00:00:03.9974913 18 for (int i = 0; i < 2000; i++) 19 { 20 using (SqlConnection con = new SqlConnection(constr)) 21 { 22 con.Open(); 23 con.Close(); 24 } 25 } 26 watch.Stop(); 27 Console.WriteLine(watch.Elapsed); 28 29 Console.WriteLine("连接打开了又关闭了。"); 30 Console.ReadKey(); 31 #endregion 32 } 33 }
图中的连接池中存放的是没有被销毁的SqlConncetion对象《该对象已经与数据库建立了连接》,下次再Open()时直接拿来使用,不用再次创建连接。
证明上图:
解析:《当con建立与数据库的连接,在对象内部会创建一个和数据库的连接,并把这个连接赋给连接对象内部的一个属性InnerConnection,即:con对象只是对内部InnerConnection对象的包装,其实真正连接数据库的是con内部的InnerConnection对象,接下来我们就可以使用了,使用的时候用的是InnerConnection对象。当我关闭这个连接的时候,即执行con.Close(),其实是把InnerConnection属性放到了连接池中,内部真正访问数据库连接的对象并没有关闭,即InnerConnection并没有关闭,销毁与关闭的都是con对象,当你下次再创建一个连接对象的时候,因为连接字符串和上次的完全相同,虽然创建了一个con对象,但是内部的InnerConnection对象任然使用的是连接池中的InnerConnection对象。由于InnerConnection对象与数据库的连接没有关闭,所以第n(n>1)次使用的时候也就不需要打开了。》
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 //默认使用连接池的连接字符串 6 //string constr = "Data Source=zxtiger;Initial 7 8 Catalog=itcastcn;Integrated Security=True"; 9 //using (SqlConnection con = new SqlConnection(constr)) 10 //{ 11 // con.Open(); 12 //} 13 14 //using (SqlConnection con1 = new SqlConnection(constr)) 15 //{ 16 // con1.Open(); 17 //}//出了作用域自动Dispose 18 19 string constr = "Data Source=zxtiger;Initial 20 21 Catalog=Itcastcn;Integrated Security=True;Pooling=false";//Pooling=false 22 23 表示禁用连接池 24 25 26 //InnerConnection是SqlConnection的私有成员,点不出来,通过反 27 28 射获取... 29 PropertyInfo pinfo = typeof(SqlConnection).GetProperty 30 31 ("InnerConnection", BindingFlags.NonPublic | BindingFlags.Instance); 32 SqlConnection con1 = new SqlConnection(constr); 33 object obj1 = null; 34 object obj2 = null; 35 36 using (con1) 37 { 38 con1.Open(); 39 //获取con1内部的InnerConnection对象。 40 obj1 = pinfo.GetValue(con1, null); 41 con1.Close(); 42 } 43 44 45 // 两次打开同一个连接(因为第二次使用的还是这个连接字符串) 46 // string constr1 = "Data Source=zxtiger;Initial 47 48 Catalog=Itcastcn;User ID=sa;Password=124;"; 49 SqlConnection con2 = new SqlConnection(constr); 50 using (con2) 51 { 52 con2.Open(); 53 //获取第二个对象的InnerConnection 54 obj2 = pinfo.GetValue(con2, null); 55 con2.Close(); 56 } 57 //比较这两个对象是否是同一个对象 58 if (obj1 == obj2) 59 { 60 Console.WriteLine("是同一个对象"); 61 } 62 else 63 { 64 Console.WriteLine("不是同一个对象!"); 65 } 66 Console.ReadKey(); 67 68 69 } 70 }
销毁的是con对象,内部的InnerConnection没有销毁,而是放到了连接池中。