Can CLR execution continue after 'THROW' is encountered in T-SQL?
It appears that this behavior is specific to connections using
"Context Connection = true;". I have tried to get around this by writing out the
try-catch-finally structure instead of using the
using macro, but that had no effect.
A Microsoft Connect bug was filed almost 3 months ago regarding this behavior. In that Connect bug it was speculated that
THROW raises a ThreadAbortException that cannot be reset via the Thread.ResetAbort method. I tried explicitly catching this exception, and even calling
Thread.ResetAbort when catching the generic
Exception, but to no avail. So I am not sure if a
ThreadAbortException is really being called, but regardless, the current process ends immediately. And, it even displays the error as a T-SQL error and not a .NET Framework error, which is odd.
The reporter of that Connect bug tested on SQL Server 2014, and I tested on SQL Server 2012. I cannot say for certain if this behavior still exists in SQL Server 2016, but I strongly suspect that it does given that there doesn't seem to be much effort (if any) put into fixing and/or improving SQL Server's CLR Integration (i.e. SQLCLR). So for now, and likely the foreseeable future, there are three possible work-arounds that have worked for me:
RAISERROR(); RETURN;for procs that might be called by SQLCLR objects. The only downsides I can think of are:
- Can't set a custom
- Can't re-throw to send the original, system-defined
ERROR_NUMBERto the caller
- Can't set a custom
Wrap your query in a T-SQL
String _Query = @" BEGIN TRY EXEC dbo.TestThrowSql @CauseError; END TRY BEGIN CATCH DECLARE @ErrorMessage NVARCHAR(4000); SET @ErrorMessage = ERROR_MESSAGE(); RAISERROR(@ErrorMessage, 16, 1); END CATCH; ";
The benefit here is that you can continue to use
THROWand it will work as expected when called by non-SQLCLR app code, by SQLCLR app code that is not using the Context Connection, by other Stored Procedures, in SQL Agent jobs, etc. That and you don't have to go back and edit any existing Stored Procedures :-).
- Switch to using a regular / external connection string. The downsides here are:
- The Context Connection is much faster.
- The Context Connection can be done in a
- The Context Connection has access to session-based items (i.e.
CONTEXT_INFO, local temporary tables, etc.)