网站导航网学 原创论文 原创专题 网站设计 最新系统 原创论文 论文降重 发表论文 论文发表 UI设计定制 论文答辩PPT格式排版 期刊发表 论文专题
返回网学首页
网学原创论文
最新论文 推荐专题 热门论文 论文专题
当前位置: 网学 > 设计资源 > .Net编程 > 正文

ado.net连接池

论文降重修改服务、格式排版等 获取论文 论文降重及排版 论文发表 相关服务

ado.NET中提供了连接池的功能,多数开发人员很少设置它,因为它是默认的。

界面设置如下图:

关闭连接池也很简单,在连接字符串如下:

  1. Data Source=(local);Initial Catalog=AdventureWorks;Integrated Security=SSPI;Pooling=False; 

但连接池的本质是什么样的呢?

用Reflector,打开System.Data.SqlClient.SqlConnection的ConnectionString属性的设置值的方法,如下:

  1. private void ConnectionString_Set(string value) 
  2.  
  3.  
  4.     DbConnectionOptions userConnectionOptions = null
  5.  
  6.     DbConnectionPoolGroup group = this.ConnectionFactory.GetConnectionPoolGroup(value, nullref userConnectionOptions); 
  7.  
  8.     DbConnectionInternal innerConnection = this.InnerConnection; 
  9.  
  10.     bool allowSetConnectionString = innerConnection.AllowSetConnectionString; 
  11.  
  12.     if (allowSetConnectionString) 
  13.  
  14.     { 
  15.  
  16.         allowSetConnectionString= this.SetInnerConnectionFrom(DbConnectionClosedBusy.SingletonInstance, innerConnection); 
  17.  
  18.         if (allowSetConnectionString) 
  19.  
  20.         { 
  21.  
  22.             this._userConnectionOptions = userConnectionOptions; 
  23.  
  24.             this._poolGroup = group; 
  25.  
  26.             this._innerConnection = DbConnectionClosedNeverOpened.SingletonInstance; 
  27.  
  28.         } 
  29.  
  30.     } 
  31.  
  32.     if (!allowSetConnectionString) 
  33.  
  34.     { 
  35.  
  36.         throw ADP.OpenConnectionPropertySet("ConnectionString", innerConnection.State); 
  37.  
  38.     } 
  39.  
  40.     if (Bid.TraceOn) 
  41.  
  42.     { 
  43.  
  44.         string str = (userConnectionOptions != null) ? userConnectionOptions.UsersConnectionStringForTrace() : ""
  45.  
  46.         Bid.Trace("<prov.DbConnectionHelper.ConnectionString_Set|API> %d#, '%ls'\n"this.ObjectID, str); 
  47.  
  48.     } 
  49.  
  50.  
  51. 再连接 到红色的GetConnectionPoolGroup方法,如下代码 
  52.  
  53.  internal DbConnectionPoolGroup GetConnectionPoolGroup(string connectionString, DbConnectionPoolGroupOptions poolOptions, ref DbConnectionOptions userConnectionOptions) 
  54.  
  55.  
  56.     DbConnectionPoolGroup group; 
  57.  
  58.     if (ADP.IsEmpty(connectionString)) 
  59.  
  60.     { 
  61.  
  62.         return null
  63.  
  64.     } 
  65.  
  66.     if (!this._connectionPoolGroups.TryGetValue(connectionString, out group) || (group.IsDisabled && (group.PoolGroupOptions != null))) 
  67.  
  68.     { 
  69.  
  70.         DbConnectionOptions options = this.CreateConnectionOptions(connectionString, userConnectionOptions); 
  71.  
  72.         if (options == null
  73.  
  74.         { 
  75.  
  76.             throw ADP.InternalConnectionError(ADP.ConnectionError.ConnectionOptionsMissing); 
  77.  
  78.         } 
  79.  
  80.         string str = connectionString; 
  81.  
  82.         if (userConnectionOptions == null
  83.  
  84.         { 
  85.  
  86.             userConnectionOptions = options; 
  87.  
  88.             str = options.Expand(); 
  89.  
  90.             if (str != connectionString) 
  91.  
  92.             { 
  93.  
  94.                 return this.GetConnectionPoolGroup(str, nullref userConnectionOptions); 
  95.  
  96.             } 
  97.  
  98.         } 
  99.  
  100.         if ((poolOptions == null) && ADP.IsWindowsNT) 
  101.  
  102.         { 
  103.  
  104.             if (group != null
  105.  
  106.             { 
  107.  
  108.                 poolOptions = group.PoolGroupOptions; 
  109.  
  110.             } 
  111.  
  112.             else 
  113.  
  114.             { 
  115.  
  116.                 poolOptions = this.CreateConnectionPoolGroupOptions(options); 
  117.  
  118.             } 
  119.  
  120.         } 
  121.  
  122.         DbConnectionPoolGroup group2 = new DbConnectionPoolGroup(options, poolOptions) { 
  123.  
  124.             ProviderInfo = this.CreateConnectionPoolGroupProviderInfo(options) 
  125.  
  126.         }; 
  127.  
  128.         lock (this
  129.  
  130.         { 
  131.  
  132.             Dictionary<string, DbConnectionPoolGroup> dictionary = this._connectionPoolGroups; 
  133.  
  134.             if (!dictionary.TryGetValue(str, out group)) 
  135.  
  136.             { 
  137.  
  138.                 Dictionary<string, DbConnectionPoolGroup> dictionary2 = new Dictionary<string, DbConnectionPoolGroup>(1 + dictionary.Count); 
  139.  
  140.                 foreach (KeyValuePair<string, DbConnectionPoolGroup> pair in dictionary) 
  141.  
  142.                 { 
  143.  
  144.                     dictionary2.Add(pair.Key, pair.Value); 
  145.  
  146.                 } 
  147.  
  148.                 dictionary2.Add(str, group2); 
  149.  
  150.                 this.PerformanceCounters.NumberOfActiveConnectionPoolGroups.Increment(); 
  151.  
  152.                 group = group2; 
  153.  
  154.                 this._connectionPoolGroups = dictionary2; 
  155.  
  156.             } 
  157.  
  158.             return group; 
  159.  
  160.         } 
  161.  
  162.     } 
  163.  
  164.     if (userConnectionOptions == null
  165.  
  166.     { 
  167.  
  168.         userConnectionOptions = group.ConnectionOptions; 
  169.  
  170.     } 
  171.  
  172.     return group; 
  173.  
  174.  
  175. TryGetValue是判断是否存在连接字符串为connectionString的连接,存在返回到group,不存在就调用CreateConnectionOptions创建一个DbConnectionOptions,最后用 
  176.  
  177. lock (this
  178.  
  179.         { 
  180.  
  181.             Dictionary<string, DbConnectionPoolGroup> dictionary = this._connectionPoolGroups; 
  182.  
  183.             if (!dictionary.TryGetValue(str, out group)) 
  184.  
  185.             { 
  186.  
  187.                 Dictionary<string, DbConnectionPoolGroup> dictionary2 = new Dictionary<string, DbConnectionPoolGroup>(1 + dictionary.Count); 
  188.  
  189.                 foreach (KeyValuePair<string, DbConnectionPoolGroup> pair in dictionary) 
  190.  
  191.                 { 
  192.  
  193.                     dictionary2.Add(pair.Key, pair.Value); 
  194.  
  195.                 } 
  196.  
  197.                 dictionary2.Add(str, group2); 
  198.  
  199.                 this.PerformanceCounters.NumberOfActiveConnectionPoolGroups.Increment(); 
  200.  
  201.                 group = group2; 
  202.  
  203.                 this._connectionPoolGroups = dictionary2; 
  204.  
  205.             } 
  206.  
  207.             return group; 
  208.  
  209.         } 

这段代码放到连接池中,在这里,可能显示的看到,ado.NET的连接池实质上是一个Dictionary<string, DbConnectionPoolGroup>泛型集合。

所谓的连接池,就是一个与连接对象Connection相关的集合,这不只是简单的集合,而是有一定的机制在内部。我们做开发时,可能建立Connection连接对象,关闭连接对象,有时候还调用Dispose来释放连接。下次再用时,便重新实例化一个连接。但在池中的连接不随连接对象的Close或Dispose而释放。如果下次重新建立连接,连接字符串与前一次完全一模一样,则连接池就会把上次可用的连接对象赋给连接去用。如果两个连接字符串有一点不一样,即使在某一个地方多一个空格,连接池也不会以为是相同的连接,这点微软可能在内部只直接去比较两个字符串了,而不是比较连接数据库字符串的键值互相匹配。

连接池的好处就是保留连接对象,防止下次重头再来实例化一个连接对象。


(说明:可能找到结果后觉得非常简单,但怎么找到结果的,却是费了很大劲,几乎是5个小时,所以相把找到结果的过程简单说一下:

一开始用Reflector发现SqlConnection中有一个PoolGroup的属性,于是就想在运行时候比较两个SqlConnection对象的这个属性,但由于这个属性是的访问修饰符是internal的,不能直接访问,只有用反射,代码(是经过优化的)如下:

  1. string constr1 = "Data Source=(local);Initial Catalog=AdventureWorks;Integrated Security=SSPI;"
  2.  
  3.            string constr2 = "Data Source=(local);Initial Catalog=Pubs;Integrated Security=SSPI;"
  4.  
  5.            string AssMark = "System.Data,Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
  6.  
  7.            Assembly ass = Assembly.Load(AssMark); 
  8.  
  9.  
  10.  
  11.            Type SqlConType = null
  12.  
  13.            foreach (Type conType in ass.GetExportedTypes()) 
  14.  
  15.            { 
  16.  
  17.                Console.WriteLine(conType .ToString ()); 
  18.  
  19.                if ("System.Data.SqlClient.SqlConnection" == conType.ToString()) 
  20.  
  21.                { 
  22.  
  23.                    SqlConType = conType; 
  24.  
  25.                } 
  26.  
  27.            } 
  28.  
  29.            if (SqlConType != null
  30.  
  31.            { 
  32.  
  33.                Type types1 = new Type[0]; 
  34.  
  35.                ConstructorInfo constructorInfoObj1 = SqlConType.GetConstructor( 
  36.  
  37.                     BindingFlags.Instance | BindingFlags.Public, null
  38.  
  39.                     CallingConventions.HasThis, types1, null); 
  40.  
  41.                SqlConnection con1 = (SqlConnection)constructorInfoObj1.Invoke(null); 
  42.  
  43.                con1.ConnectionString = constr1;            
  44.  
  45.                SqlConnection con2 = (SqlConnection)constructorInfoObj1.Invoke(null); 
  46.  
  47.                con2.ConnectionString = constr2; 
  48.  
  49.                PropertyInfo PI = SqlConType.GetProperty("PoolGroup", BindingFlags.Instance | BindingFlags.NonPublic); 
  50.  
  51.                object poolGroup1 = PI.GetValue(con1, null); 
  52.  
  53.                object poolGroup2 = PI.GetValue(con2, null);  
  54.  
  55.            } 

然后在倒数第一行设置断点,为比较poolGroup1和poolGroup2的不同,结果发现,当连接字符串一样时,这两个对象的_objectID相同,字符串有一点不同就会不同,这点说明连接池中是用字符串本身比较的,而不是字符串中键值对进行比较。同还发现当con1和con2的ConnectionString不赋值时这两个对象都是null,由此说明关键是ConnectionString赋值上,所以才开始用Reflector查看这个属性的赋值方法,才有上面的代码。)

设为首页 | 加入收藏 | 网学首页 | 原创论文 | 计算机原创
版权所有 网学网 [Myeducs.cn] 您电脑的分辨率是 像素
Copyright 2008-2020 myeducs.Cn www.myeducs.Cn All Rights Reserved 湘ICP备09003080号 常年法律顾问:王律师