为什么不能通过try / catch SqlException捕获SqlException类型的异常?

时间:2019-04-06 02:02:16

标签: c# try-catch sqlexception

我有以下代码:

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

我故意违反唯一键引发SQL异常。但是,该异常是由Exception而不是SqlException捕获的。当我检查InnerException的详细信息时,例外的类型为System.Data.SqlClient.SqlException

InnerException Details

为什么SQL异常仅被通用Exception捕获?

2 个答案:

答案 0 :(得分:4)

问题是您试图捕获SqlException,但这不是异常类型:这是InnerException。

如果user10954641是正确的,并且它是UpdateException,则可以简单地捕获到这一点:

try
{
}
catch (UpdateException e)
{
}

如果是不同的异常,则捕获实际上引发的任何异常类型。另外,您可以有条件地捕获InnerException为SqlException的异常:

try
{
}
catch (Exception e) when (e.InnerException is SqlException)
{
}

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

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

public void MakeDatabaseCall()
{
    throw new SqlException();
}

ThrowException()的调用最终将产生错误形式MakeDatabaseCall(),但是异常类型将不是SqlException,因为我们将其包装在另一个异常中(在这种情况下,该异常基类):Exception。但是,由于我们要将MakeDatabaseCall()引发的异常传递到构造函数中,因此我们的“哦,哦!”例外将在其SqlException字段中包含InnerException

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

try
{
}
catch(SqlException e)
{
    //catches an SqlException
}

try
{
}
catch(Exception e) when (e is SqlException)
{
    //catches an SqlException
}

很明显,在我们的ThrowException示例中,Exception不是从SqlException派生的,因此catch (SqlException e)将不匹配。

答案 1 :(得分:0)

事实证明,异常类型为EntityCommandExecutionException,是从DataException派生的。

我本来打算对SqlException.Number执行一些逻辑,这就是为什么我试图捕获SqlException的原因。

但是,要解决此问题,请抓住DataException,然后将InnerException投射到SqlException

try
{
    Data.CreateUserAndAccount.ExecuteProcedure(accountName, firstName, lastName, email, password);
    return String.Empty;
}
catch (DataException procedureError)
{
    SqlException sqlError = (SqlException)procedureError.InnerException;
    string result = IdentifyError(sqlError);
    return result;
}