使用语句是否需要 Try/Catch/finally 来处理异常?

发布于 2025-01-01 07:35:18 字数 1548 浏览 0 评论 0原文

我想知道如何使用语句处理异常? 我是否需要使用 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

I wonder how to use statement handles exceptions?
Do I need to wrap the using statements with a Try/Cath/Finally clause in order to be sure that the SqlConnection object is closed and disposed even if the containing code throws an exception?

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

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

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

发布评论

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

评论(3

椒妓 2025-01-08 07:35:18

usingtryfinally 放入代码中,并自动调用 .Dispose() 并最终调用 。 Close() 因为DbConnection.Dispose()调用了Close(),但是没有catch,所以你需要添加catch 超过 using 块,比如这

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

vs

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

所以看到这个你可能会认为 Try/Catch/FinallyUsing 更好,因为在任何情况下你都需要处理 using错误,但事实并非如此

如果在 .Close().Dispose() 期间发生任何错误,第一个示例也会处理该错误,但在第二种情况下,您必须将 try-catchfinally 块中。

详细了解避免使用语句出现问题 (MSDN)

希望这能解答您的问题。

using puts try and finally in your code and automatically it calls .Dispose() and eventually .Close() coz DbConnection.Dispose() calls Close(), but there is no catch, so you will need to add catch over using block, some thing like this

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

vs

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

So looking at this you might think Try/Catch/Finally is better than Using, coz in using in any case you need to handle error, but it's not.

If there is any error during .Close() or .Dispose() occurs, the first sample will handle that too, but in second case you will have to put try-catch in finally block.

Read more about Avoiding Problems with the Using Statement (MSDN)

Hope this answers your question.

爱情眠于流年 2025-01-08 07:35:18

您不需要再次写出它,它会在编译的代码中自动创建。

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

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

阅读这篇文章了解更多详细信息:理解 C# 中的“using”块

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

You dont require to write it out again its get created automatically in complied code..

The answer is in C# but its works same way in VB.NET

using block in C# comes very handly while dealing with disposable objects. Disposable objects are those objects that can explicitly release the resources they use when called to dispose. As we know .Net garbage collection is non-deterministic so you can’t predict when exactly the object will be garbage collected.

Read this post for more in details : understanding ‘using’ block in C#

CS file code

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 code

.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
孤独患者 2025-01-08 07:35:18

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

Yes, you need the try catch block e.g. for logging the exception as shown in your code.
The using block makes sure that Dispose is called but does not handle exceptions.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文