简体   繁体   English

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

[英]Why is my code leaking connections?

Question: 题:

Why is the following code leaking connections ? 为什么以下代码会泄漏连接?

    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;
    }

If I go into SQL-Server activity monitor, I see Session 68 如果我进入SQL-Server活动监视器,则看到会话68

SELECT * FROM T_Benutzergruppen

Additional question: 附加问题:

If question: 如果有问题:

If I comment out everything except the ConnectionStringBuilder, and only execute the below code in this function, why does it leak a connection, too ? 如果我注释掉ConnectionStringBuilder以外的所有内容,并且仅在此函数中执行以下代码,为什么它也会泄漏连接?

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

Note: 注意:
The executenonquery makes no sense, it's just there for testing purposes. executenonquery毫无意义,仅用于测试目的。

If I let it run in the debugger, I see that sqlcon.Close(); 如果我让它在调试器中运行,则会看到sqlcon.Close();。

get's executed, so the problem is not the 得到执行,所以问题不在于

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

Connection Pooling. 连接池。 Don't worry about it. 不用担心

This is normal behavior. 这是正常现象。

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

ADO.Net pools connections so that they can be re-used because they are relatively expensive to create. ADO.Net合并连接,以便可以重新使用它们,因为它们创建起来比较昂贵。

Connecting to a database server typically consists of several time-consuming steps. 连接到数据库服务器通常包括几个耗时的步骤。 A physical channel such as a socket or a named pipe must be established, the initial handshake with the server must occur, the connection string information must be parsed, the connection must be authenticated by the server, checks must be run for enlisting in the current transaction, and so on. 必须建立一个物理通道(例如套接字或命名管道),必须与服务器进行初始握手,必须解析连接字符串信息,必须由服务器对连接进行身份验证,必须运行检查才能在当前列表中注册交易等等。

In practice, most applications use only one or a few different configurations for connections. 实际上,大多数应用程序仅使用一种或几种不同的配置进行连接。 This means that during application execution, many identical connections will be repeatedly opened and closed. 这意味着在应用程序执行期间,许多相同的连接将被反复打开和关闭。 To minimize the cost of opening connections, ADO.NET uses an optimization technique called connection pooling. 为了最大程度地减少打开连接的成本,ADO.NET使用了一种称为连接池的优化技术。

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

Also, there is no need to explicitly call .Close(). 同样,也无需显式调用.Close()。 Your using block will call IDisposable.Dispose() , which will close the connection properly. 您的using块将调用IDisposable.Dispose() ,它将正确关闭连接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM