为什么 try/catch SqlException 没有捕获到 SqlException 类型的异常?
Why is exception of type SqlException not being caught by 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
.
为什么 SQL 异常只能被泛型 Exception
捕获?
问题是您正在尝试捕获 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
因为我们将其包装在另一个异常中(在本例中异常基础 class): Exception
。但是,因为我们将 MakeDatabaseCall()
抛出的异常传递给构造函数,我们的 "Uh oh!" 异常将在其 InnerException
字段中包含 SqlException
。
当您使用 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)
不会匹配。
事实证明异常是从 DataException
派生的 EntityCommandExecutionException
类型。
我原本打算在 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;
}
我有以下代码:
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
.
为什么 SQL 异常只能被泛型 Exception
捕获?
问题是您正在尝试捕获 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
因为我们将其包装在另一个异常中(在本例中异常基础 class): Exception
。但是,因为我们将 MakeDatabaseCall()
抛出的异常传递给构造函数,我们的 "Uh oh!" 异常将在其 InnerException
字段中包含 SqlException
。
当您使用 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)
不会匹配。
事实证明异常是从 DataException
派生的 EntityCommandExecutionException
类型。
我原本打算在 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;
}