2016-04-26 18 views
2

私の.NETコードでは、データベーストランザクション内で(TransactionScopeを使用)、ネストされたブロックをTransactionScopeOption.Suppressに含めると、ネストされたブロック内のコマンドが外側のブロックがロールバックします。私は、これはT-SQLで行うことができれば、検索しようとした.NET TransactionScopeOption.Suppressに相当するT-SQL

using (TransactionScope txnScope = new TransactionScope(TransactionScopeOption.Required)) 
{ 
    db.ExecuteNonQuery(CommandType.Text, "Insert Into Business(Value) Values('Some Value')"); 

    using (TransactionScope txnLogging = new TransactionScope(TransactionScopeOption.Suppress)) 
    { 
     db.ExecuteNonQuery(CommandType.Text, "Insert Into Logging(LogMsg) Values('Log Message')"); 
     txnLogging.Complete(); 
    } 

    // Something goes wrong here. Logging is still committed 

    txnScope.Complete(); 
} 

:後 は、コードサンプルです。いくつかの人々がOPENROWSETを推奨しましたが、使用するにはあまり「エレガント」に見えません。また、T-SQLコードに接続情報を入れるのは悪い考えです。

これまでSQL Service Brokerを使用していましたが、Transactional Messagingもサポートしています。これは、データベーストランザクションがコミットされるまでメッセージがキューにポストされないことを意味します。

私の要件:アプリケーションストアドプロシージャは、ストアドプロシージャの外部で開始された暗黙のトランザクション内で、一部のサードパーティアプリケーションによって起動されています。そして私は、私のストアドプロシージャ内のエラー(同じデータベース内のデータベーステーブル内の)を捕捉して記録できるようにしたい。私は例外を再スローして、サードパーティのアプリケーションにトランザクションをロールバックさせ、操作が失敗したことを知ることができるようにする必要があります。

+0

.NETコードはサードパーティの.NETコードで呼び出されていますか? – usr

+0

可変テーブルを見ましたか? – Shaneis

+0

@usr - 私は第三者のアプリケーションコードを知らない。私の質問に投稿した.NETコードは、T-SQLコードで同じことをしたいと思っていただけです。 –

答えて

4

remote proc transaction Promotionオプションをfalseに設定してループバックリンクサーバーを設定し、TSQLでアクセスするか、SQLサーバーのCLRプロシージャを使用してトランザクション外に新しい接続を作成して作業を行うことができます。

どちらの方法もHow to create an autonomous transaction in SQL Server 2008で提案されています。

どちらの方法も新しい接続の作成を伴います。この機能をネイティブに提供することを要求するopen connect itemがあります。

+0

CLRプロシージャーのオプションが検討されていました。しかし、ループバックリンクサーバーオプションはずっと簡単です。どうもありがとう! リンクサーバーオプションのパフォーマンスが著しく低下していますか?これは、例外条件(大部分はストアドプロシージャのキャッチブロック)でのみ使用されます。 –

+0

1つではなく2つの接続が私が考えることができる主なものですが、これは通常のものであるかのようには聞こえません。 –

0

テーブル変数の値は、ROLLBACKを超えて存在します。

したがって次の例では、削除しようとしていたすべての行を永続化テーブルに挿入し、後でOUTPUTとテーブル変数を組み合わせることで照会できます。

-- First, create our table 
CREATE TABLE [dbo].[DateTest] ([Date_Test_Id] INT IDENTITY(1, 1), [Test_Date] datetime2(3)); 

-- Populate it with 15,000,000 rows 
-- from 1st Jan 1900 to 1st Jan 2017. 
INSERT INTO [dbo].[DateTest] ([Test_Date]) 
SELECT 
TOP (15000000) 
    DATEADD(DAY, 0, ABS(CHECKSUM(NEWID())) % 42734) 
    FROM [sys].[messages] AS [m1] 
    CROSS JOIN [sys].[messages] AS [m2]; 

BEGIN TRAN; 

BEGIN TRY 

    DECLARE @logger TABLE ([Date_Test_Id] INT, [Test_Date] DATETIME); 

    -- Delete every 1000 row 
    DELETE FROM [dbo].[DateTest] 
    OUTPUT deleted.Date_Test_Id, deleted.Test_Date INTO @logger 
    WHERE [Date_Test_Id] % 1000 = 0; 

    -- Make it fail 
    SELECT 1/0 

    -- So this will never happen 
    COMMIT TRANSACTION; 

END TRY 
BEGIN CATCH 

    ROLLBACK TRAN 
    SELECT * INTO dbo.logger FROM @logger; 

END CATCH; 

SELECT * FROM dbo.logger; 

DROP TABLE dbo.logger; 
+0

「第三者のアプリケーション」がトランザクションをロールバックしているとの質問があります。ロールバックはproc自体にはありません(ただし、これが起こる場合はオプションであればこれが良い解決策になります) –

関連する問題