8

コア サービスを使用してパブリケーション ターゲットへの宛先の追加と削除を支援するクラスを作成しました。宛先は通常、コア サービスを介して文字列 (XML コンテンツを含む) として公開されるため、その周りに独自のラッパーを作成するなどしました。

現在、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);
}

しかし、違いはありませんでした。私が現在トランザクションに参加しているかどうかを判断し、何らかの方法でそのトランザクションを「使用」する方法はありますか? 私はトランザクションを要求したくありません。トランザクションで操作するオプションが欲しいだけです。

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

4

1 に答える 1

3

これに最適なリソースは次のとおりです。WCF トランザクションの伝播

少なくとも 1 つの手順がありません。また、バインディングでトランザクションを有効にする必要があります。

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

私が現在トランザクションに参加しているかどうかを判断し、何らかの方法でそのトランザクションを「使用」する方法はありますか?

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

WCF トランザクションの伝播の図 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、例外が発生します。)

于 2012-09-13T17:41:59.327 に答える