简体   繁体   中英

Why is exception of type SqlException not being caught by try/catch SqlException?

I have the following code:

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

I am intentionally throwing SQL exceptions by violating a unique key. However, the exception is caught by Exception and not SqlException . When I examine the InnerException details, the exception is of type System.Data.SqlClient.SqlException .

InnerException详细信息

Why is the SQL exception only being caught by the generic Exception ?

The problem is that you're trying to catch SqlException , but that's not the exception type: it's the InnerException.

If user10954641 is right, and its an UpdateException , you could simply catch that:

try
{
}
catch (UpdateException e)
{
}

If it's a different exception, then catch whatever exception type is actually thrown. Alternatively, you could conditionally catch exceptions where the InnerException is SqlException :

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

If you're wondering why catch (SqlException) doesn't work, consider the following code:

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

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

A call to ThrowException() will ultimately produce an error form MakeDatabaseCall() , but the exception type will not be SqlException because we're wrapping it in another exception (in this case the exception base class): Exception . But, because we're passing the exception thrown by MakeDatabaseCall() into the constructor, our "Uh oh!" exception will contain the SqlException in its InnerException field.

When you use try / catch(ExceptionType e) , you're instructing .NET to pattern match the exception before deciding which catch statement to enter. For the sake of illustration, the two pieces of code below are roughly equivalent :

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

and

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

Clearly in our ThrowException example, Exception is not derived from SqlException , so catch (SqlException e) won't match.

It turns out the exception is of type EntityCommandExecutionException which is derived from DataException .

I originally intended to perform some logic on SqlException.Number , which is why I was trying to catch a SqlException .

However, to solve this, catch DataException and then cast the InnerException to 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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM