是否需要使用Using语句来尝试/捕获/最终处理异常?

时间:2012-01-31 09:23:28

标签: .net vb.net ado.net using-statement

我想知道如何使用语句处理异常? 我是否需要使用 Try / Cath / Finally 子句包装using语句,以确保即使包含的代码抛出异常,SqlConnection对象也会被关闭和处理?

Public Function GetUserAccountKeyByUsername(ByVal pUsername As String) As Int32
    If String.IsNullOrEmpty(pUsername) Then
        Throw New ArgumentNullException("pUsername", "Username is missing")
    End If

    Dim o As Object
    Dim userAccountKey As Int32
    Dim SQL As StringBuilder = New StringBuilder()

    With SQL
        .Append("SELECT USER_KEY ")
        .Append("FROM USER ")
        .Append("WHERE USERNAME = @Username ")
    End With

    Try
        Using conn As SqlConnection = New SqlConnection(ConnectionString)
            conn.Open()
            Using cmd As SqlCommand = New SqlCommand(SQL.ToString, conn)
                Try
                    cmd.CommandTimeout = Convert.ToInt32(ConfigurationManager.AppSettings("SQLQueryLimitTime"))
                    cmd.Parameters.Add(New SqlParameter("@Username", SqlDbType.VarChar)).Value = pUsername
                    o = cmd.ExecuteScalar()
                    If (o IsNot Nothing) AndAlso Not (IsDBNull(o)) Then
                        userAccountKey = Convert.ToInt32(o)
                    End If
                Catch ex As Exception
                    _log.logError(ex, cmd)
                End Try
            End Using
        End Using
    Catch ex As Exception
        _log.logError(ex, conn.ConnectionString)
    Finally
        conn.Close()
        conn.Dispose()
    End Try
    Return userAccountKey
End Function

3 个答案:

答案 0 :(得分:10)

usingtryfinally放入您的代码中,并自动调用.Dispose(),最后.Close()调用DbConnection.Dispose()调用Close() },但没有捕获,所以你需要在catch块上添加using,这样的事情

try
{
   using(some resource)
   {
   }
}
catch(Exception)
{
}

VS

try
{
}
catch(Exception)
{
}
finally{ }

所以看看这个你可能会认为尝试/抓住/最后使用更好,因为在using中你需要处理错误, 但不是

如果在.Close().Dispose()期间出现任何错误,第一个示例也会处理,但在第二种情况下,您必须将try-catch放入finally块。

详细了解Avoiding Problems with the Using Statement (MSDN)

希望这能回答你的问题。

答案 1 :(得分:3)

你不需要再把它写出来,它会在编译代码中自动创建..

答案在C#中,但在VB.NET中的工作方式相同

在处理一次性物体时,使用C#中的块非常方便。一次性对象是那些可以在调用dispose时显式释放它们使用的资源的对象。我们知道.Net垃圾收集是非确定性的,因此您无法预测对象何时会被垃圾收集。

阅读这篇文章了解更多详情:understanding ‘using’ block in C#

CS文件代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BlogSamples
{
    class Program
    {
        static void Main(string[] args)
        {
            using (Car myCar = new Car(1))
            {
                myCar.Run();
            }
        }
    }
}

MSIL代码

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       37 (0x25)
  .maxstack  2
  .locals init ([0] class BlogSamples.Car myCar,
           [1] bool CS$4$0000)
  IL_0000:  nop
  IL_0001:  ldc.i4.1
  IL_0002:  newobj     instance void BlogSamples.Car::.ctor(int32)
  IL_0007:  stloc.0
  .try
  {
    IL_0008:  nop
    IL_0009:  ldloc.0
    IL_000a:  callvirt   instance void BlogSamples.Car::Run()
    IL_000f:  nop
    IL_0010:  nop
    IL_0011:  leave.s    IL_0023
  }  // end .try
  finally
  {
    IL_0013:  ldloc.0
    IL_0014:  ldnull
    IL_0015:  ceq
    IL_0017:  stloc.1
    IL_0018:  ldloc.1
    IL_0019:  brtrue.s   IL_0022
    IL_001b:  ldloc.0
    IL_001c:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()
    IL_0021:  nop
    IL_0022:  endfinally
  }  // end handler
  IL_0023:  nop
  IL_0024:  ret
} // end of method Program::Main

答案 2 :(得分:2)

是的,你需要try catch块,例如用于记录代码中显示的异常。 using块确保调用Dispose但不处理异常。