ここで注意してください!TransactionAutoComplete=true を設定すると、サービスが正常に戻った場合、トランザクションはコミットされます。未処理の例外 (例外をキャッチして受信メッセージを返すため、ほとんどの場合、例外はありません) がある場合にのみ、トランザクションはロールバックされます。http://msdn.microsoft.com/en-us/library/system.servicemodel.operationbehaviorattribute.transactionautocomplete.aspxを参照してください。
いくつかの DAL 呼び出しを正常に実行したが、他の例外 (NullReferenceException など) が発生したシナリオについて考えてみてください。未処理の例外は発生していませんが、クライアントは ErrorReceipt を受け取るため、メソッドが完了するとトランザクションがコミットされます。
あなたのシナリオでは、トランザクションを自分で管理する必要があると思います。例えば:
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = false)]
public Receipt Foo()
{
// Create TransactionScope using the ambient transaction
using (var scope = new TransactionScope() )
{
try { DAL.Foo(); return Receipt.CreateSuccessReceipt(); scope.Complete(); }
catch (Exception ex) { return Receipt.CreateErrorReceipt(ex); }
}
}
トランザクション内にすべてをラップするヘルパー メソッドを作成することでボイラープレート コードを削除するか、ポリシー インジェクション/インターセプト/アスペクトを使用してトランザクションを管理することができます。
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = false)]
public Receipt Foo()
{
return ProcessWithTransaction(() =>
{
DAL.Foo();
return Receipt.CreateSuccessReceipt();
}
, (ex) =>
{
return Receipt.CreateErrorReceipt(ex);
}
);
}
T ProcessWithTransaction<T>(Func<T> processor, Func<Exception, T> exceptionHandler)
{
using (var scope = new TransactionScope())
{
try
{
T returnValue = processor();
scope.Complete();
return returnValue;
}
catch (Exception e)
{
return exceptionHandler(e);
}
}
}
例外シールドを使用する必要があると述べています。エラーが発生したときにフォールトをスローすることを嫌わない場合は、Enterprise Library Exception Handling Block の例外シールドを使用して、途中で情報をログに記録することもできます (必要な場合)。
そのルートに進むことにした場合、コードは次のようになります。
[OperationBehavior(TransactionScopeRequired = true)]
public void Foo()
{
// Resolve the default ExceptionManager object from the container.
ExceptionManager exManager = EnterpriseLibraryContainer.Current.GetInstance<ExceptionManager>();
exManager.Process(() =>
{
DAL.Foo();
return Receipt.CreateSuccessReceipt();
},
"ExceptionShielding");
}
その後、エンタープライズ ライブラリは (構成を介して) 例外をキャッチし、クライアントに返される新しい FaultException に置き換えます。