Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何捕获带有“异常”的异常;使用;在C中#_C#_Sql_Ado.net - Fatal编程技术网

C# 如何捕获带有“异常”的异常;使用;在C中#

C# 如何捕获带有“异常”的异常;使用;在C中#,c#,sql,ado.net,C#,Sql,Ado.net,鉴于此代码: using (var conn = new SqlConnection("...")) { conn.Open(); using (var cmd = conn.CreateCommand()) { cmd.CommandText = "..."; using (var reader = cmd.ExecuteReader()) { while (reader.Read())

鉴于此代码:

using (var conn = new SqlConnection("..."))
{
    conn.Open();
    using (var cmd = conn.CreateCommand())
    {
        cmd.CommandText = "...";
        using (var reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                // ...
            }
        }
    }
}
我已经习惯于为我的数据访问编写try/catch/finally块,然而,我正在接触“使用”,这似乎是一种更简单的方法。然而,我正试图找出如何捕获可能发生的异常

你能给我举个例子说明你是如何捕捉异常的吗

编辑以添加:


我被引导相信“使用”是我的try/catch/finally块的替代品。我知道使用不会捕获异常。那么这是如何替代的呢?

使用语句与异常无关。使用块只是确保在使用块中的对象退出该块时对其调用Dispose。即:

using(SqlConnection conn = new SqlConnection(conStr))
{
   //use conn
}//Dispose is called here on conn.

如果打开连接引发异常(或该块中的任何其他异常),它仍然会冒泡到顶部,并且与任何其他未处理的异常一样。

使用
不是为了捕获异常而设计的;它旨在为您提供一种简单的方法,将
try
/
最终
包裹在需要处置的对象周围。如果您需要捕获并处理异常,那么您需要将其扩展为完整的
try
/
捕获
/
最后
或在整个事件周围放置一个包含
try
/
捕获


要回答您的编辑(是否使用
替换
尝试
/
catch
/
最后
?),则不是。在大多数情况下,当使用一次性资源时,您不会在那里处理异常,因为通常情况下,您无法做任何有用的事情。因此,它提供了一种方便的方法,可以确保资源得到清理,而不管您尝试执行的操作是否有效

通常,处理可支配资源的代码的工作级别太低,无法决定失败时的正确操作,因此将异常传播给调用方,调用方可以决定要采取的操作(例如重试、失败、日志等)。
您倾向于使用带有一次性资源的
catch
块的唯一地方是,如果您要转换异常(我假设,这就是您的数据访问层正在做的事情)。

如果您想捕获异常,您可能应该返回使用try/catch/finally。只需将.Dispose()调用放在finally块中。

将所有using语句包装到try/catch中。正如其他人所说,使用是为了清理实现IDisposable接口的类

try
{

 using (var conn = new SqlConnection("..."))
 {
    conn.Open();
    using (var cmd = conn.CreateCommand())
    {
        cmd.CommandText = "...";
        using (var reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                // ...
            }
        }
    }
 }
}
catch(Exception ex)
{
//Handle, log, rethrow exception
}
您仍然可以像以前一样捕获(或忽略)异常。关键是,您不再需要担心如何处理数据库连接

也就是说,如果您的应用程序出于某些其他原因(例如,日志记录)需要捕获异常,请继续,但如果您只想处理数据库连接,则不再需要这样做:

using (SqlConnection conn = new SqlConnection(...))
{
    // do your db work here
    // whatever happens the connection will be safely disposed
}
如果出于其他原因希望捕获异常,您仍然可以这样做:

try
{
    using (SqlConnection conn = new SqlConnection(...))
    {
        // do your db work here
        // whatever happens the connection will be safely disposed
    }
}
catch (Exception ex)
{
    // do your stuff here (eg, logging)
    // nb: the connection will already have been disposed at this point
}
finally
{
    // if you need it
}
语法上的糖是什么

var cmd = new SqlCommand("SELECT * FROM Customers");
try
{
    cmd.CommandTimeout = 60000;
    ...
}
finally
{
    if (cmd != null)
        cmd.Dispose();
}
因此,当人们告诉你“使用”是try/catch/finally的替代品时,他们是在暗示你应该使用长手形式,但要添加catch块:

var cmd = new SqlCommand("SELECT * FROM Customers");
try
{
    cmd.CommandTimeout = 60000;
    ...
}
catch (Exception ex)
{
    ...//your stuff here
}
finally
{
    if (cmd != null)
        cmd.Dispose();
}

放入一个
try catch
块中,使用
块/s来阻止
。用于对象处置的隐式
finally
语句将在外部块
catch
语句及其内容之前执行。

try/catch/finally并在我的finally块中调用dispose如何更好?Erik,为什么要在finally块中调用dispose?什么时候可以使用using语句?如果使用finally块,那么必须在try块之外声明对象……在内部,这与using语句将生成的IL相同。一开始我想不出那个解决方案,试着在“使用”偏执中写“try”子句,然后当然编译器说wtf正在做:D。然后到了第页。他说:“哦,我的天哪,我怎么能不那样想呢?”他可以把使用包装成一个try/catch块。如果捕获到错误,在输入catch之前将调用Dispose(如果存在)。这是真的,但是您还有一个缩进级别,using语句不再那么方便了。我更喜欢用try/catch/finally来处理所有的事情(但这是一个很小的风格)。但是即使使用简单的错误处理,也可以很容易地编写代码,看起来它调用了
Dispose()
,但在某些情况下失败了<代码>使用()
至少可以确保正确地清理它,即使它几乎不可能进行细粒度异常处理。这很有趣。我想知道你是否要在这里插入你的头:)如果在try块中创建cmd,你不能在finally块中调用dispose。这与其他答案有什么不同,例如Chuck Conway的答案?它解释了隐式“finally”语句将在外部块“catch”语句之前执行。我认为这是一个重要的重点,我认为这是在最初的问题中隐含的要求,即使没有明确表达,或者至少我理解了这一需要
var cmd = new SqlCommand("SELECT * FROM Customers");
try
{
    cmd.CommandTimeout = 60000;
    ...
}
catch (Exception ex)
{
    ...//your stuff here
}
finally
{
    if (cmd != null)
        cmd.Dispose();
}