使用 IDisposable 时在哪里放置 try/catch

发布于 2024-12-12 07:03:12 字数 752 浏览 1 评论 0 原文

我只是建议将整个 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();
    }
}

在此应用程序中,确保与数据库的连接不会因异常而开始累积更为重要。

I was just advised to put an entire using block inside a try, otherwise the using scope will prevent the exception from being caught. However, wouldn't that prevent the using from properly disposing its resources if an exception were thrown? If I have the code below, where should I put the try blocks?

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

In this application, it's far more important to ensure connections to the database don't start accumulating due to exceptions.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

风吹雨成花 2024-12-19 07:03:12

using 语句已经可以防止连接累积 - 它通过有效地成为一个 try/finally 块来为您完成清理工作对 finally 块中的 Dispose 的调用。如果您还想要一个 try/catch 块,您可以将其放在内部或外部 - 但您确定它不应该位于更高的水平?您实际上期望如何处理异常?

顺便说一句,当命令即将被释放时,尚不清楚为什么要清除命令中的参数...

我鼓励您也在 using 语句中声明变量,这样您就不会最终尝试在块之外读取它们:

using (SqlConnection connSQL = new SqlConnection(strConn)) {

通常,更愿意为变量提供尽可能窄的范围。哦,您的 SqlDataReader 也应该位于 using 语句中。无论如何,这可能并不重要,因为您要关闭连接和命令,但我会按照原则这样做 - 它实现了 IDisposable,因此您应该处置它。

哦,目前您迭代 sqlParameters 的方式相当冗长。 foreach 使它更简单,即使没有,我也会使用 for (int i = 0; i 除非我有理由相信这不是一个“简单”的数组。

所以,我的等效代码看起来像这样:

using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();
    using (SqlCommand command = new SqlCommand(strPreparedStatement, connection))
    {
        if (sqlParameters != null)
        {
            // If sqlParameter is an array, you can just use
            // command.Parameters.AddRange(sqlParameters) instead
            foreach (SqlParameter parameter in sqlParameters)
            {
                command.Parameters.Add(parameter);
            }
        }
        using (SqlDataReader reader = command.ExecuteReader())
        {
            DataTable table = new DataTable();
            // Perform any extra initialization here
            table.Load(reader);
            return table;
        }
    }
}

The using statement will already prevent connections from accumulating - it does the cleanup side of things for you, by effectively being a try/finally block with a call to Dispose in the finally block. If you also want a try/catch block, you can put it either inside or outside - but are you sure it shouldn't be at a higher level? How are you actually expecting to handle the exception?

As an aside, it's not clear why you're clearing the parameters from the command when the command is about to be disposed anyway...

I would encourage you to declare the variables within the using statements too, so that you don't end up trying to read from them outside the block:

using (SqlConnection connSQL = new SqlConnection(strConn)) {

In general, prefer to give your variables as narrow a scope as possible. Oh, and your SqlDataReader should be in a using statement too. It may not matter as you're closing the connection and the command anyway, but I would do it as a point of principle - it implements IDisposable, so you should dispose it.

Oh, and your way of iterating over sqlParameters is fairly longwinded at the moment. foreach makes it simpler, and even if it didn't I'd use for (int i = 0; i < sqlParameters.Length; i++) unless I had reason to believe it wasn't a "simple" array.

So, my equivalent code would look something like this:

using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();
    using (SqlCommand command = new SqlCommand(strPreparedStatement, connection))
    {
        if (sqlParameters != null)
        {
            // If sqlParameter is an array, you can just use
            // command.Parameters.AddRange(sqlParameters) instead
            foreach (SqlParameter parameter in sqlParameters)
            {
                command.Parameters.Add(parameter);
            }
        }
        using (SqlDataReader reader = command.ExecuteReader())
        {
            DataTable table = new DataTable();
            // Perform any extra initialization here
            table.Load(reader);
            return table;
        }
    }
}
情定在深秋 2024-12-19 07:03:12

您还需要将数据读取器包装在 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 连接和命令的方法可以确保正确释放它们。

You need to wrap the data reader in a using statement as well since it is a disposable resource:

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

I have also made the connection, command and data reader objects locally defined into this block scope.

As far as a try/finally statement is concerned you no longer need it as the using statements ensure that the Dispose method will be invoked even in the event of exceptions. And this method for sql connections and commands ensures to properly release them.

多彩岁月 2024-12-19 07:03:12

不需要放置 try catch 因为 using 隐式实现它,实际上它使用 try finally 并确保它会释放对象。

这是关于 try catch 和使用的 MSDN 使用示例

{
  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.
}

There is no need to put try catch because using implement it implicitly, in fact it uses try finally and sure it will disposes objects.

This is MSDN using Sample about try catch and using:

{
  Font font1 = new Font("Arial", 10.0f);
  try
  {
    byte charset = font1.GdiCharSet;
  }
  finally
  {
    if (font1 != null)
      ((IDisposable)font1).Dispose();
  }
}

is equal to:

using (Font font3 = new Font("Arial", 10.0f),
            font4 = new Font("Arial", 10.0f))
{
    // Use font3 and font4.
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文