为什么 SqlException 类型的异常没有被 try/catch SqlException 捕获?

0 c# sqlexception try-catch

我有以下代码:

    try
    {
        Data.CreateUserAndAccount.ExecuteProcedure(accountName, firstName, lastName, email, password);
        return String.Empty;
    }
    catch (SqlException databaseError)
    {
        string result = IdentifyError(databaseError);
        return result;
    }
    catch  (Exception)
    {
        throw;
    }
Run Code Online (Sandbox Code Playgroud)

我通过违反唯一键故意抛出 SQL 异常。但是,异常被Exception而非捕获SqlException。当我检查InnerException详细信息时,异常类型为System.Data.SqlClient.SqlException

内部异常详情

为什么 SQL 异常只能被泛型捕获Exception

Joh*_*ica 6

问题是您正在尝试 catch SqlException,但这不是异常类型:它是 InnerException。

如果user10954641是对的,并且它是UpdateException,你可以简单地捕捉到:

try
{
}
catch (UpdateException e)
{
}
Run Code Online (Sandbox Code Playgroud)

如果是不同的异常,则捕获实际抛出的任何异常类型。或者,您可以有条件地捕获 InnerException 为的异常SqlException

try
{
}
catch (Exception e) when (e.InnerException is SqlException)
{
}
Run Code Online (Sandbox Code Playgroud)

如果您想知道为什么catch (SqlException)不起作用,请考虑以下代码:

public void ThrowException()
{
    try
    {
        MakeDatabaseCall();
    }
    catch (Exception e)
    {
        throw new Exception("Uh oh!", e);
    }
}

public void MakeDatabaseCall()
{
    throw new SqlException();
}
Run Code Online (Sandbox Code Playgroud)

对 的调用ThrowException()最终会产生一个错误 form MakeDatabaseCall(),但异常类型不会是SqlException因为我们将它包装在另一个异常中(在本例中为异常基类):Exception。但是,因为我们将抛出的异常传递给MakeDatabaseCall()构造函数,所以我们的“哦哦!” 异常将SqlException在其InnerException字段中包含。

当您使用try/ 时catch(ExceptionType e),您是在指示 .NET 在决定catch输入哪个语句之前对异常进行模式匹配。为了说明起见,下面的两段代码大致等效

try
{
}
catch(SqlException e)
{
    //catches an SqlException
}
Run Code Online (Sandbox Code Playgroud)

try
{
}
catch(Exception e) when (e is SqlException)
{
    //catches an SqlException
}
Run Code Online (Sandbox Code Playgroud)

显然,在我们的ThrowException示例中,Exception不是派生自SqlException,因此catch (SqlException e)不会匹配。