In C# 6 they added exception filtering. This allows you to conditionally catch exceptions.
To filter exceptions, you use the when clause after the catch clause, like this:
catch (SqlException ex) when (ex.Number == -2)
Code language: C# (cs)
Any SqlException that doesn’t meet the condition will not be caught.
Previously, without exception filtering, you’d have to handle that scenario in the catch block and rethrow, like this:
catch (SqlException ex)
{
if (ex.Number == -2)
{
//handle exception properly
}
else
{
throw;
}
}
Code language: C# (cs)
Exception filtering example – conditionally catching transient SqlException
Here’s a full example of using exception filtering to catch transient SQL exceptions. If it’s a transient error, such as a timeout, it retries the query up to three times. Notice that the retry threshold is part of the exception filtering clause. This is because I only want to catch and handle exceptions if I still want to retry the query. You can basically have any conditions you want.
static async Task Main(string[] args)
{
var conString = ConfigurationManager.ConnectionStrings["SQLServer"].ConnectionString;
HashSet<int> transientSqlErrors = new HashSet<int>()
{
-2, 258
};
int attempts = 1;
int retryThreshold = 3;
TimeSpan commandTimeout = TimeSpan.FromSeconds(1);
using (SqlConnection con = new SqlConnection(conString))
{
while (true)
{
try
{
var data = await con.QueryAsync("[spGetTeamsInDivision]",
new { conference = "NFC", division = "North" },
commandType: CommandType.StoredProcedure,
commandTimeout: commandTimeout.Seconds);
Console.WriteLine(data);
}
catch (SqlException ex)
when (transientSqlErrors.Contains(ex.Number) && attempts <= retryThreshold)
{
Console.WriteLine("Transient SQL error. Increasing timeout and retrying in 5 seconds");
commandTimeout = TimeSpan.FromSeconds(10);
}
await Task.Delay(TimeSpan.FromSeconds(5));
attempts++;
}
}
}
Code language: C# (cs)