如果 .NET SqlConnection 对象未关闭,它会导致内存泄漏吗?

Can a .NET SqlConnection object cause a memory leak if it is not closed?

我知道您需要在 SqlConnection 对象上调用 .Close() 以在完成后将基础 SQL 连接释放回池中;但如果您不这样做,.NET 对象是否会在超出范围后仍保留在内存中?我问是因为我正在处理一些内存泄漏的代码,我注意到 SqlConnection 对象没有被关闭或处置(它们被创建、打开,然后被允许超出范围)。

始终使用 using(...) 来处理 sqlConn 和 sqlCmd。如果仍然存在内存泄漏, 然后向微软报告错误...如果你正确处理,那里应该没有内存泄漏

using (SqlConnection sqlConn = new SqlConnection(....))
{
  using (SqlCommand sqlCmd = new SqlCommand(....))
  {
    .... do something here with your sqlConn and sqlCmd
  }  // sqlCmd will be properly disposed here
}  // sqlConn will be properly disposed here

问题不是内存泄漏。问题是与 SQL 服务器的连接保持打开状态,这意味着该连接不可用于需要与该服务器通信的其他对象。

如果连接超出范围并被垃圾收集和处置,连接将最终关闭,但不知道什么时候会发生。您的应用程序在给定时间只能打开这么多 SQL 个连接,而 SQL 服务器本身只能支持这么多连接。

把它想象成一个负责人从图书馆借书。如果你不 return 这本书,它最终会回到图书馆,因为有一天你会死,当有人清理你的房子时,他们会找到这本书并将它送回图书馆。但如果每个人都这样做,那么在图书馆就很难找到书了。因此,在我们真正准备好阅读之前,我们不会检查这本书,并且我们会在完成后立即 return 它。

与 SQL 连接相同。除非您需要它们,否则不要打开它们,并在您用完它们后尽快关闭它们。并且,如其他答案所示,using 通过确保无需使用 try/finally.

来处理连接(也关闭它)来简化它

关于如何指示数据库更新有 2 种首选方法 "using" 和 "try catch"

public void PerformStoredProcedure()
{
    string cs = System.Configuration.ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString; // reading by name DBCS out of the web.config file
    using (SqlConnection connection = new SqlConnection(cs))
    {
        SqlCommand cmd = new SqlCommand("spDoMyStoredProcudere", connection);
        cmd.CommandType = System.Data.CommandType.StoredProcedure;
        cmd.Parameters.AddWithValue("@good", TextBox1.Text + "%"); // input for stored procedure
        connection.Open();

        //--
        GridView1.DataSource = cmd.EndExecuteReader();
        GridView1.DataBind();
    }
} 

使用的好处是它会自动关闭。

另一种方法是 try catch 构造

protected void Page_Load(object sender, EventArgs e)
{
    string cs; // conection string.
    cs = "data source=.; "; //servername (.) = local database password. 
 // cs = cs + "user id=sa; password=xxxxx"; using sql passwords authentication.
    cs = cs + "integrated security=SSPI"; // using windows nt authentication.

    //its better to store connnection in web.config files. so all form pages can use it.

    cs = System.Configuration.ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString; // reading by name DBCS out of the web.config file

    SqlConnection con = new SqlConnection(cs);
    try
    {  // if any problem ocures we still close the connection in finally.
        //SqlCommand cmd = new SqlCommand("Select * from tblSample", con);  //execture this command on this coneection on this table


        SqlCommand cmd = new SqlCommand("Select title, good from tblSample",con);
        con.Open(); 

        GridView1.DataSource = cmd.ExecuteReader(); //execure reader T_SQL statement that returns more then 1 value
        //cmd.ExecuteNonQuery  //for insert or update or delete
        //cmd.ExecuteScalar //for single value return
        GridView1.DataBind();
    }
    catch
    {
        Response.Write("uh oh we got an error");
    }
    finally
    {
        con.Close();
    }

虽然 using 主要用于异国情调的场景,但 catch 选项可能也不错,但它需要更多的输入。

如果我在 20 分钟左右后正确提醒,则默认情况下,如果没有任何操作发生,IIS 会话将终止。