2012-08-08 31 views
1

问题:为什么我的代码泄漏连接?

为什么以下代码泄漏连接?

public System.Data.DataTable GetDataTable() 
    { 
     System.Data.DataTable dt = new System.Data.DataTable(); 
     string strConnectionString = "Data Source=localhost;Initial Catalog=MyDb;User Id=SomeOne;Password=TopSecret;Persist Security Info=False;MultipleActiveResultSets=False;Packet Size=4096;"; 
     System.Data.SqlClient.SqlConnectionStringBuilder csb = new System.Data.SqlClient.SqlConnectionStringBuilder(strConnectionString); 
     csb.IntegratedSecurity = true; 


     string strSQL = "SELECT * FROM T_Benutzergruppen"; 

     using (System.Data.SqlClient.SqlConnection sqlcon = new System.Data.SqlClient.SqlConnection(csb.ConnectionString)) 
     { 
      using (System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(strSQL, sqlcon)) 
      { 
       if (sqlcon.State != System.Data.ConnectionState.Open) 
       { 
        sqlcon.Open(); 
       } 

       // First attempt 
       //System.Data.SqlClient.SqlDataAdapter sqlda = new System.Data.SqlClient.SqlDataAdapter("SELECT * FROM T_Benutzer", sqlcon); 
       //sqlda.Fill(dt); 

       cmd.ExecuteNonQuery(); 
      } 

      if(sqlcon.State != System.Data.ConnectionState.Closed) 
       sqlcon.Close(); 
     } 
     //sqlcon.ConnectionString = csb.ConnectionString; 

     // Second attempt 
     //System.Data.SqlClient.SqlDataAdapter sqlda = new System.Data.SqlClient.SqlDataAdapter("SELECT * FROM T_Benutzer", csb.ConnectionString); 
     //sqlda.Fill(dt); 


     return dt; 
    } 

如果我去到SQL-Server活动监视器,我看到会议68

SELECT * FROM T_Benutzergruppen 

其他问题:

如果问题:

如果我注释掉之外的所有ConnectionStringBuilder ,并且只在这个函数中执行下面的代码,为什么它也会泄漏一个连接呢?

// Second attempt 
System.Data.SqlClient.SqlDataAdapter sqlda = new System.Data.SqlClient.SqlDataAdapter("SELECT * FROM T_Benutzer", csb.ConnectionString); 
sqlda.Fill(dt); 

注:
为ExecuteNonQuery是没有意义的,它只是有用于测试目的。

如果我让它在调试器中运行,我会看到那个sqlcon.Close(); ;

获取的执行,所以这个问题是不是

if(sqlcon.State != System.Data.ConnectionState.Closed) 
+0

你不需要在你的'SqlConnection'对象上明确调用'.Close()','using'块会在你超出范围时为你做这件事。你的代码很好,因为其他人已经指出这只是工作中的连接池。 – James 2012-08-08 09:05:10

+0

@James:是的。现在我知道默认情况下池已经打开。 – 2012-08-08 09:14:09

回答

3

连接池。不要担心。

这是正常行为。

http://msdn.microsoft.com/en-us/library/8xx3tyca(v=vs.100).aspx

+0

很好,谢谢。设置csb.Pooling = false;解决了这两个问题。现在我终于可以在代码的其余部分搜索连接泄漏。 – 2012-08-08 09:05:53

+0

@Quandary:确保在生产设置中不关闭连接池。这将*杀死*性能。 – 2012-08-08 09:07:05

+0

@ Eric J.:别担心,我知道。只是调试除了池以外的泄漏,并且池化连接以我的方式搜索ActivityMonitor中的泄漏地点。 – 2012-08-08 09:08:48

2

ADO.Net池连接,使得它们可以重新使用,因为它们创造相对昂贵。

连接到数据库服务器通常包含几个耗时的步骤。必须建立物理通道(如套接字或命名管道),必须与服务器进行初始握手,必须解析连接字符串信息,连接必须由服务器进行身份验证,必须运行检查才能登录当前交易等。

实际上,大多数应用程序仅使用一种或几种不同的配置进行连接。这意味着在应用程序执行过程中,许多相同的连接将被重复打开和关闭。为了最小化开放连接的成本,ADO.NET使用称为连接池的优化技术。

http://msdn.microsoft.com/en-us/library/8xx3tyca(v=vs.100).aspx

而且,也没有必要显式调用.Close()。您的使用块将调用IDisposable.Dispose(),这将正确关闭连接。

+0

我只是不知道默认情况下是否启用了pooling。以为这是我的错。 – 2012-08-08 09:07:04

+2

是的,这是一个wises默认值。不要在生产代码中关闭它:-) – 2012-08-08 09:07:26

+0

哦,谁在乎,生产服务器不是我的部门;) – 2012-08-08 10:09:59