私は両方の質問に対する答えを見つけたと信じています...
運用に関してTransactionalは、「周囲の」トランザクションがあるとは思いません。データベース操作の後に例外をスローするだけでこれを証明しましたが、確かに、とにかくデータはコミットされます。トランザクション スコープを宣言するための推奨される方法があるかどうかを知りたいです。
[OperationBehavior(TransactionScopeRequired = true)]
public void MyServiceOperation(){ ... }
//or using the TransactionScope
public void MyServiceOperation()
{
using(var transScope = new TransactionScope(...)){ ... }
}
再試行機能についてはReceiveContext、次のブログを有効にする必要があるようです:
[ServiceContract]
public interface IMyService
{
[OperationContract(IsOneWay=true)]
[ReceiveContextEnabled(ManualControl = true)]
void MyServiceOperation();
// and in the service implementation:
[OperationBehavior]
public void MyServiceOperation()
{
var incomingProperties = OperationContext.Current.IncomingMessageProperties;
var property = incomingProperties[BrokeredMessageProperty.Name] as BrokeredMessageProperty;
//Complete the Message
ReceiveContext receiveContext;
if (ReceiveContext.TryGet(incomingProperties, out receiveContext))
{
//Do Something
receiveContext.Complete(TimeSpan.FromSeconds(10.0d));
}
else
{
throw new InvalidOperationException("...");
}
}
アップデート:
もう少し深く掘り下げた後、Service Bus 1.0 で単純なバニラ、コントラクト ファースト、IIS でホストされる WCF を使用している場合、OperationContext` の補完は実際にはオプションではないことがわかりました (理由はわかりませんが、誰かがこれに光を当ててくれることを願っています)
私が見つけたのは、トランザクション動作の唯一の適切なオプションは次のとおりです。
[OperationBehavior]
public void MyServiceOperation()
{
using(var transScope = new TransactionScope(...))
{
DbWork();
transScope.Complete();
}
Client.SendToServiceBus(); // <-- Cannot be part of transaction, otherwise
// exceptions will be thrown!
}
MSMQ などとは異なり、このパターンでは、サービス バスへのメッセージの送信が失敗した場合に操作全体をロールバックできないという問題が残ります。(もちろん、誰かがもっとよく知っている場合を除きます...)
これはまた、独自の再試行ロジックと、前のステップがコミットされたことを次のステップで検証する何らかのメカニズムをロールバックする必要があることも意味します。うん!
私の理解では、Workflow Services と仲介されたメッセージを直接処理することで、すぐに使用できる再試行機能が提供されます。しかし、AppFabric を介して IIS でワークフロー サービスを IIS でホストしている場合、Microsoft はどういうわけか、サービス バスへの送信をカバーするトランザクションを取得する方法を見つけ出しました。(その仕組みを知っている人がいたら教えてください!)