C# – Exception filters – conditionally catch exceptions

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)

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; } }

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++; } } }

Leave a Comment