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

C# 为什么try/catch-SqlException没有捕获类型为SqlException的异常?,c#,try-catch,sqlexception,C#,Try Catch,Sqlexception,我有以下代码: try { Data.CreateUserAndAccount.ExecuteProcedure(accountName, firstName, lastName, email, password); return String.Empty; } catch (SqlException databaseError) { string result = IdentifyError(databas

我有以下代码:

    try
    {
        Data.CreateUserAndAccount.ExecuteProcedure(accountName, firstName, lastName, email, password);
        return String.Empty;
    }
    catch (SqlException databaseError)
    {
        string result = IdentifyError(databaseError);
        return result;
    }
    catch  (Exception)
    {
        throw;
    }
public void ThrowException()
{
    try
    {
        MakeDatabaseCall();
    }
    catch (Exception e)
    {
        throw new Exception("Uh oh!", e);
    }
}

public void MakeDatabaseCall()
{
    throw new SqlException();
}
我故意通过违反唯一键来抛出SQL异常。但是,异常被异常捕获,而不是被SqlException捕获。当我检查InnerException详细信息时,异常类型为System.Data.SqlClient.SqlException


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

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

如果是正确的,并且是UpdateException,您可以简单地捕捉到:

try
{
}
catch (UpdateException e)
{
}
如果是不同的异常,则捕获实际抛出的任何异常类型。或者,您可以有条件地捕获InnerException为SqlException的异常:

如果您想知道为什么catch SqLeExver不起作用,请考虑下面的代码:

    try
    {
        Data.CreateUserAndAccount.ExecuteProcedure(accountName, firstName, lastName, email, password);
        return String.Empty;
    }
    catch (SqlException databaseError)
    {
        string result = IdentifyError(databaseError);
        return result;
    }
    catch  (Exception)
    {
        throw;
    }
public void ThrowException()
{
    try
    {
        MakeDatabaseCall();
    }
    catch (Exception e)
    {
        throw new Exception("Uh oh!", e);
    }
}

public void MakeDatabaseCall()
{
    throw new SqlException();
}
对ThroweException的调用最终将生成一个错误表单MakeDatabaseCall,但异常类型将不是SqlException,因为在本例中,我们将它包装在另一个异常中,即异常基类:exception。但是,因为我们正在将MakeDatabaseCall引发的异常传递到构造函数中,所以我们的!异常将在其InnerException字段中包含SqlException

当您使用try/catchExceptionType e时,您指示.NET在决定输入哪个catch语句之前先对异常进行模式匹配。为了便于说明,下面的两段代码大致相当:


显然,在我们的ThroweException示例中,异常不是从SqlException派生的,因此catch SqlException e将不匹配。

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

我最初打算对SqlException.Number执行一些逻辑,这就是我试图捕获SqlException的原因

但是,要解决此问题,请捕获DataException,然后将InnerException强制转换为SqlException:


因为SqlException可能是InnerException。实际的异常类型是什么?可能是UpdateException/DbUpdateException,请查看以下答案:实际的异常类型是EntityCommandExecutionException@John@user10954641。
try
{
}
catch(Exception e) when (e is SqlException)
{
    //catches an 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;
}