3

私がやっていることに遠く離れた何かを見つけることができませんでした。予算上の懸念から、私はあなたに何らかの援助を求めなければなりません。私は現在、さまざまな量のレコードをインポートできるインポートアプリケーションを作成しています。おそらく、この可変数は非常に高く、潜在的には何百万というものになるでしょう。 WCFストリーミングを利用して、処理するためにデータチャンクをサーバーに送信します。サーバー側では、検証のためにtemp SQLテーブルにデータをダンプします。そこから、TPLを使用して設定された数のレコードを抽出し、永続的SQLストレージリポジトリに挿入します。より多くのことが関与していますが、要するにその大部分です。現時点で未解決の問題は、ユーザーがいつでもインポートをキャンセルできるようにすることだけです。これは、これらのレコードの保存中にキャンセルが発生する可能性があることを意味します。挿入/更新されたすべてのレコードをロールバックできる必要があります。 TPLを使用してレコードを処理しているので、トランザクションを共有するのは非常に困難です。私はMSDN(非常によく似ている、http://msdn.microsoft.com/en-us/library/system.transactions.dependenttransaction(v=VS.100).aspx)で概説されているDependentTransactionのアプローチを使用しています。ここではいくつかのコードスニペットは、次のとおりです。このTPL反復インサイドTPL /並列処理でDependentTransactionまたは複数のDependentTransactionsを使用することはできますか?

var currentTransaction = System.Transactions.Transaction.Current; 

...

// DataTable is simply a placeholder for X amount of records from the SQL temp table 
var partitions = Partitioner.Create(0, DataTable.Rows.Count, 100); 
Parallel.ForEach(partitions, (partition, state) => 
        { 
         using (var parallelTransaction = new TransactionScope(currentTransaction.DependentClone((DependentCloneOption.RollbackIfNotComplete))) 

、多くの選択、挿入および更新の発生があります。可能であれば、これらのすべてが同じ取引で発生することを願っています。少なくとも、TransactionScopeはすべてをロールバックできるように管理する必要があります。私は、 "トランザクションコンテキストが既に使用中"であるというエラーを受け取り、その後すぐに中止します。

私はDependentTransactionを正しく使用していませんか?私の要求も可能ですか?トランザクションは通常シーケンシャルであり、このコンテキストでは使用されませんが、簡単にするために、挿入されたレコードを追跡して手動でロールバックするための機能を実装する必要がないので、トランザクションが理想的です。

提案がありますか?

注:Parallelイテレーションのローカルステートアプローチを試しましたが、私が何をしても、すべて同じ例外が生成されます。また、RollbackIfNotCompleteまたはBlockCommitUntilCompleteを使用しても何の影響もありません。

+0

私はこの記事を見てきました(http://stackoverflow.com/questions/2186698/how-do-distributed-transactions-behave-with-multiple-connections-to-the-same-db-i)これが可能でないかと疑問に思います。その投稿は、私がやろうとしていることを概説しています。これが変わったのか誰にも分かりますか? –

+0

レコードは一時テーブルにインポートされます。インポートが完了する前に一時テーブルの処理(検証)を開始しますか?インポートが完了するまで処理を開始できませんか?それらが取り消された場合、それは一時表を削除するのと同じように簡単です。何百万というレコードを持つトランザクションは非常に大きなトランザクションです。トランザクションが完了し、大きなトランザクション・ログが必要になるまでコミットされていないデータがあることは知っていますか? – Paparazzi

答えて

0

SQL Serverトランザクションを管理する最適な場所は、T-SQLコード内です。同じSQL Serverにすべてのデータを挿入/更新/削除しているので、T-SQLコードのトランザクション内で選択/挿入/更新を実行するだけの理由はありません。ここでは、使用できるシンプルなテンプレートを紹介します。

-- REFERENCE: http://aleemkhan.wordpress.com/2006/07/21/t-sql-error-handling-pattern-for-nested-transactions-and-stored-procedures/ 
    -- ====================================================================================== 
    -- STANDARD HEADER FOR TRANSACTION LOGIC THAT WILL ALSO HANDLE BEING A NESTED TRANSACTION 
    -- FOR SQL 2005 AND UP 
    -- ====================================================================================== 
    SET XACT_ABORT ON; 
    BEGIN TRY 
    DECLARE @TranStarted bit; SET @TranStarted = 0 
    IF(@@TRANCOUNT = 0) BEGIN BEGIN TRANSACTION; SET @TranStarted = 1; END ELSE SET @TranStarted = 0 
    -- ====================================================================================== 




    -- ================================================================== 
    -- ***** SQL CODE FOR SELECTS/INSERTS/UPDATES/DELETES GOES HERE ***** 
    -- ================================================================== 




    -- ====================================================================================== 
    -- STANDARD FOOTER FOR TRANSACTION LOGIC THAT WILL ALSO HANDLE BEING A NESTED TRANSACTION 
    -- FOR SQL 2005 AND UP 
    -- ====================================================================================== 
    IF(@TranStarted = 1 AND (XACT_STATE()) = 1) BEGIN SET @TranStarted = 0; COMMIT TRANSACTION; END 
    RETURN(0) 
    END TRY 
    BEGIN CATCH 
     DECLARE @ErrorMessage nvarchar(4000) 
      ,@ErrorNumber int 
      ,@ErrorSeverity int 
      ,@ErrorState int; 
     SELECT @ErrorMessage = ERROR_MESSAGE() + CHAR(13) + 'Actual Code Line that took the error: ' + CONVERT(nvarchar, ERROR_LINE()) 
               + CHAR(13) + 'Actual Proc that took the error: ' + CONVERT(nvarchar(126), ERROR_PROCEDURE()) 
      ,@ErrorSeverity = ERROR_SEVERITY() 
      ,@ErrorState = ERROR_STATE() 
      ,@ErrorNumber = ERROR_NUMBER(); 

    IF(@TranStarted = 1 AND (XACT_STATE()) = -1) BEGIN SET @TranStarted = 0; ROLLBACK TRANSACTION; END 
    RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState); 
    END CATCH 
    -- ====================================================================================== 
関連する問題