John Gordon
I would think that binning exceptions by SqlState might be the best way to approach this problem if you intend to tackle it. You could start by looking at the class codes, then move toward the subcodes for more information.
If you look at the ODBC errors, for instance:
http://www.microsoft.com/technet/prodtechnol/sql/70/proddocs/diag/part3/75528c16.mspx mfr=true
00 means success, 07 tends to apply to stored procedure calls, 08 means connection issue, IM indicates driver issues, etc.
I feel that severity might not offer you the level of granularity that you would desire for a global exception class (after all, if it was that easy we would have done it that way too). While I understand that you likely only run into a subset of exceptions and thus do not necessarily need to enumerate the full range of possible errors, it seems to me that you might handle it best by using SqlState or SqlState in combination with severity. For instance, timeout expired, this particular error should not be retried directly or aborted in most cases. In the case of command timeouts, you would want to: log the issue as a performance issue with a query, reconnect, raise the timeout, and retry.
There is some need to add context to these exceptions. For instance, a timeout exception in a long running query might have a different severity from a timeout exception in connecting and they would be handled differently. The level of granularity necessary will, however, depend entirely on your situation.
Hope this helps,
John (MSFT)