Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>If you can't or don't want to use DTC, and don't want to use CLR, then then you need to call the remote sp last, as you won't be able to rollback the remote sp call.</p> <pre><code>SET NOCOUNT, XACT_ABORT ON SET REMOTE_PROC_TRANSACTIONS OFF; BEGIN TRY DECLARE @ret INT BEGIN TRAN --Perform these in a transaction, so they all rollback together EXEC [LOCAL].[DB].[table].[sp1] EXEC [LOCAL].[DB].[table].[sp2] EXEC [LOCAL].[DB].[table].[sp3] EXEC [LOCAL].[DB].[table].[sp4] --We call remote sp last so that if it fails we rollback the above transactions --We'll have to assume that remote sp takes care of itself on error. EXEC [REMOTE].[DB].[table].[sp] COMMIT END TRY BEGIN CATCH --We rollback ROLLBACK -- Insert error into log table INSERT INTO [dbo].[log_table] (stamp, errorNumber, errorSeverity, errorState, errorProcedure, errorLine, errorMessage) SELECT GETDATE(), ERROR_NUMBER(), ERROR_SEVERITY(), ERROR_STATE(),ERROR_PROCEDURE(), ERROR_LINE(), ERROR_MESSAGE() END CATCH </code></pre> <p>If the local sp's depend on results from the remote stored procedure, then you can use a CLR sp (will need EXTERNAL_ACCESS permissions) and manage the transactions explicitly (basically, a roll your own DTC, but no two-phase commit. You're effectively delaying the remote commit.)</p> <pre class="lang-cs prettyprint-override"><code>//C# fragment to roll your own "DTC" This is not true two-phase commit, but //may be sufficient to meet your needs. The edge case is that if you get an error //while trying to commit the remote transaction, you cannot roll back the local tran. using(SqlConnection cnRemote = new SqlConnection("&lt;cnstring to remote&gt;")) { try { cnRemote.Open(); //Start remote transaction and call remote stored proc SqlTransaction trnRemote = cnRemote.BeginTransaction("RemoteTran"); SqlCommand cmdRemote = cnRemote.CreateCommand(); cmdRemote.Connection = cnRemote; cmdRemote.Transaction = trnRemote; cmdRemote.CommandType = CommandType.StoredProcedure; cmdRemote.CommandText = '[dbo].[sp1]'; cmdRemote.ExecuteNonQuery(); using(SqlConnection cnLocal = new SqlConnection("context connection=true")) { cnLocal.Open(); SqlTransaction trnLocal = cnLocal.BeginTransaction("LocalTran"); SqlCommand cmdLocal = cnLocal.CreateCommand(); cmdLocal.Connection = cnLocal; cmdLocal.Transaction = trnLocal; cmdLocal.CommandType = CommandType.StoredProcedure; cmdLocal.CommandText = '[dbo].[sp1]'; cmdLocal.ExecuteNonQuery(); cmdLocal.CommandText = '[dbo].[sp2]'; cmdLocal.ExecuteNonQuery(); cmdLocal.CommandText = '[dbo].[sp3]'; cmdLocal.ExecuteNonQuery(); cmdLocal.CommandText = '[dbo].[sp4]'; cmdLocal.ExecuteNonQuery(); //Commit local transaction trnLocal.Commit(); } //Commit remote transction trnRemote.Commit(); } // try catch (Exception ex) { //Cleanup stuff goes here. rollback remote tran if needed, log error, etc. } } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload