我刚建议将整个using
块放在try
内,否则using
范围将阻止异常被捕获。但是,如果抛出异常,是否会阻止using
正确处理其资源?如果我有下面的代码,我应该在哪里放置try
块?
using (connSQL = new SqlConnection(strConn))
{
connSQL.Open();
using (SqlCommand commSQL = new SqlCommand(strPreparedStatement, connSQL))
{
if (sqlParameters != null)
{
for (int i = sqlParameters.GetLowerBound(0); i <= sqlParameters.GetUpperBound(0); i++)
{
commSQL.Parameters.Add(sqlParameters[i]);
}
}
drSQL = commSQL.ExecuteReader();
dtReturn.Load(drSQL);
commSQL.Parameters.Clear();
}
}
在此应用程序中,确保与数据库的连接不会因异常而开始累积更为重要。
答案 0 :(得分:9)
using
语句已经阻止了连接的累积 - 它通过调用{{1}有效地成为try
/ finally
块来为您做清理工作。在Dispose
块中。如果您还想要finally
/ try
阻止,您可以将其置于内部或外部 - 但您确定它不应该处于更高级别吗?您实际上期望处理例外吗?
顺便说一句,目前还不清楚为什么要在命令即将被处理时清除命令中的参数......
我鼓励你在catch
语句中声明变量,这样你就不会试图在块之外读取它们了:
using
通常,您希望尽可能缩小范围。哦,您的using (SqlConnection connSQL = new SqlConnection(strConn)) {
也应该在SqlDataReader
声明中。无论如何,当你关闭连接和命令时,它可能无关紧要,但我会把它作为一个原则点 - 它实现using
,所以你应该处理它。
哦,你对IDisposable
进行迭代的方式目前相当长。 sqlParameters
使其变得更简单,即使它没有使用foreach
,除非我有理由相信它不是一个“简单”数组。
所以,我的等效代码看起来像这样:
for (int i = 0; i < sqlParameters.Length; i++)
答案 1 :(得分:2)
您需要将数据读取器包装在using语句中,因为它是一次性资源:
using (var connSQL = new SqlConnection(strConn))
using (var commSQL = connSQL.CreateCommand())
{
connSQL.Open();
commSQL.CommandText = strPreparedStatement;
if (sqlParameters != null)
{
for (int i = sqlParameters.GetLowerBound(0); i <= sqlParameters.GetUpperBound(0); i++)
{
commSQL.Parameters.Add(sqlParameters[i]);
}
}
using (var drSQL = commSQL.ExecuteReader())
{
dtReturn.Load(drSQL);
}
}
我还将连接,命令和数据读取器对象本地定义到此块范围中。
就try/finally
语句而言,您不再需要它,因为using
语句确保即使在异常情况下也会调用Dispose方法。这种用于sql连接和命令的方法可以确保正确地释放它们。
答案 2 :(得分:1)
没有必要放try
catch
因为using
隐式实现它,实际上它最后使用try并确定它会处理对象。
这是关于try catch和使用的MSDN using Sample:
{
Font font1 = new Font("Arial", 10.0f);
try
{
byte charset = font1.GdiCharSet;
}
finally
{
if (font1 != null)
((IDisposable)font1).Dispose();
}
}
等于:
using (Font font3 = new Font("Arial", 10.0f),
font4 = new Font("Arial", 10.0f))
{
// Use font3 and font4.
}