2012-09-13 8 views
8

私はコアサービスを使用して&のパブリケーションターゲットへの宛先の追加を支援するクラスを作成しました。宛先は通常、コアサービスを介して文字列として(XMLコンテンツを使用して)公開されています。そのため、自分自身でラッパーを作成しました。CoreServiceを使用してカスタムクラスでWCFトランザクションサポートを実装するにはどうすればよいですか?

ここで、2つの出版ターゲットを更新する必要があると思いますクールなトランザクションスコープを使用して、両方のターゲットが同時に更新されるようにします。

しかし、私はこれを実装することに苦労しています。

(標準CoreService WCFクライアントを使用して)作業コード:

TransactionOptions txOptions = new TransactionOptions 
        { IsolationLevel = IsolationLevel.ReadCommitted }; 
using(TransactionScope scope = new TransactionScope(
          TransactionScopeOption.Required, txOptions)) 
{ 
    PublicationTargetData publicationTarget1 = (PublicationTargetData)client.Read("tcm:0-1-65537", readOptions); 
    PublicationTargetData publicationTarget2 = (PublicationTargetData)client.Read("tcm:0-2-65537", readOptions); 

    publicationTarget1.TargetLanguage = "JSP"; 
    publicationTarget2.TargetLanguage = "JSP"; 
    client.Save(publicationTarget1, readOptions); 
    client.Save(publicationTarget2, readOptions); 

    // Stop saving 
    scope.Dispose(); 
} 

はこのコードを実行すると、正常私はscope.Dispose()前に破るとTridionので出版目標を確認した場合、それが正常にターゲットを変更する(私は変更をロールバックします変更を元に戻します)。

私は現在、「拡張された出版物ターゲット」クラスをトランザクションでも使用しようとすると、それを処分できません。

TransactionOptions options = new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted }; 
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, options)) 
{ 
    ExtendedPublicationTarget target1 = new ExtendedPublicationTarget("tcm:0-1-65537"); 
    ExtendedPublicationTarget target2 = new ExtendedPublicationTarget("tcm:0-2-65537"); 
    target1.Destinations.Add(target1.Destinations[0]); 
    target2.Destinations.Add(target2.Destinations[0]); 
    target1.Save(); 
    target2.Save(); 
    scope.Dispose(); 
} 

これは基本的に、これが問題です。私の.Save()メソッドにトランザクション性を追加するにはどうすればよいですか?私はこれをやって試してみました

[OperationContract] 
[TransactionFlow(TransactionFlowOption.Allowed)] 
public void Save() 
{ 
    _client.Save(targetData, readOptions); 
} 

しかし、それは違いはありませんでした。私が現在取引中で、どういうわけかその取引を「使用する」かどうかを判断する方法はありますか?私はトランザクションを必要としたくないだけで、1つのオプションで操作する必要があります。

非常に長い投稿を申し訳ありません...できるだけ多くの情報を提供していることを確認したかったのです。

+0

'scope'変数は' using'節にあるので、明示的に 'Dispose'を呼び出すべきではありません。代わりに 'using'ブロックが終了すると自動的に処理されます。 –

+0

あなたは「私はそれを決めることはできない」と言います。どういう意味ですか?コンパイラエラーが出ますか?例外?あるいは、コードはあなたの目標を更新しないだけですか? (PS:もし私が慣れていた通りにWCFトランザクションの名前が付けられていれば、TransactionScopeは既存のトランザクションに「ピギーバック」するか、新しいトランザクションを開始するでしょうが、WCFトランザクションに関する経験がないので、他の誰かがその仮定を確認/訂正するのを見てください)。 –

+0

こんにちはフランク、私はそれを失敗させるため、私のscope.Dispose()呼び出しをしようとしています。最初の例では正しく失敗し、2番目の例では失敗します。ちょうど私がそれを動作させるために私のクラスに追加する必要があることを理解しようとしています... –

答えて

3

このための最良のリソースは次のとおりです。WCF Transaction Propagation

あなたは少なくとも1つのステップが欠落しています。また、バインディングでトランザクションを有効にする必要があります。

<bindings> 
    <netTcpBinding> 
     <binding name = “TransactionalTCP” transactionFlow = “true” /> 
    </netTcpBinding> 
</bindings> 

私はトランザクションで、現在午前 は何とかそのトランザクションを「使用」かどうかを判断する方法はありますか?

はい。トランザクション中であるかどうかを判断するには、Transaction.Currentをチェックすることができます。取引中の場合は、明示的にオプトアウトしない限り、トランザクションを使用します。周囲の取引に関する美しい/恐ろしいことです。 WCF Transaction Propagation

図5:

class MyService : IMyContract 
{ 
    [OperationBehavior(TransactionScopeRequired = true)] 
    public void MyMethod(...) 
    { 
     Transaction transaction = Transaction.Current; 
     Debug.Assert(transaction.TransactionInformation. 
        DistributedIdentifier != Guid.Empty); 
    } 
} 

Transaction.Current.TransactionInformation.DistributedIdentifierが空の場合、トランザクションはローカルであり、 "流れ" しませんでした。 TransactionFlowOptions.Allowed構成では、トランザクションのフローが失敗した場合、メッセージは自動的に失敗します。だから、これは実際にチェックする唯一の方法です...あなたが期待するよりも簡単にフローが流れません。

プロダクションサービスにトランザクションを使用したとき、私は実際に取引が実際に流れたかどうかを呼び出し元が確信していなかったので、実際にはTransactionFlowOptions.Allowedを避けました。デプロイメントにバインド設定エラーがあった場合、すべて正常に動作しますが、ロールバックは失敗します...検出するのは非常に厄介なエラーです。だから私は必要に切り替えました。次に、呼び出し元は、提供されたトランザクションが実際に正常に渡されたことを保証できます。 (トランザクションがTransactionFlowOptions.Requiredの設定で流れない場合、例外が発生します)

+0

素晴らしい。 NetTCPバインディングをプログラムで作成し、binding.TransactionFlow = trueを設定していない - これを実行すると、すべて期待どおりに機能する。どうもありがとう –

関連する問題