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 #endregion29 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.997491318 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 #endregion32 }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 //}//出了作用域自动Dispose18 19 string constr = "Data Source=zxtiger;Initial 20 21 Catalog=Itcastcn;Integrated Security=True;Pooling=false";//Pooling=false22 23 表示禁用连接池24 25 26 //InnerConnection是SqlConnection的私有成员,点不出来,通过反27 28 射获取...29 PropertyInfo pinfo = typeof(SqlConnection).GetProperty30 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 //获取第二个对象的InnerConnection54 obj2 = pinfo.GetValue(con2, null);55 con2.Close();56 }57 //比较这两个对象是否是同一个对象58 if (obj1 == obj2)59 {60 Console.WriteLine("是同一个对象");61 }62 else63 {64 Console.WriteLine("不是同一个对象!");65 }66 Console.ReadKey();67 68 69 }70 }
销毁的是con对象,内部的InnerConnection没有销毁,而是放到了连接池中。