如果 .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 会话将终止。
我知道您需要在 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 会话将终止。