How to organize transactions?
I have services been called through the 'Guardian' method, that has TransactionScope opened for each request and complete that transaction if everything is fine:
void ExecuteWorker(...)
{
using (开发者_StackOverflowTransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew))
{
...CallLogicMethods...
scope.Complete();
}
}
One of the methods interacts with 'External' service, and in case if that interaction fails all my transaction fails also. As a result, I don't save required data (been calculated before request to external service.
void DoLogic1(...)
{
CalculateSomeData(...);
SaveCalculatedData(...);
DoRequestToExternalService(...);
}
What is the best way to resolve that issue?
Application is written using C#, .NET 4.0, MS SQL 2008.
Myself I see two solutions
Using try/catch:
void DoLogic11(...) { CalculateSomeData(...); SaveCalculatedData(...);
try { DoRequestToExternalService(...); } catch(Exception exc) { LogError(...); }
}
The lack of this approach is that I'm hiding exception from the caller. But I would like to pass error outside as an exception (to be logged, etc).
- Using 'Nested transcation', but I not sure how that works.
Here is my vision it should be:
void DoLogic12(...)
{
using (TransactionScope scopeNested = new TransactionScope(TransactionScopeOption.Suppress))
{
CalculateSomeData(...);
SaveCalculatedData(...);
scopeNested.Complete()
}
DoRequestToExternalService(...);
}
I've implemented that, tried to use, but it seems that nested transcation is committed only in case when external is committed also.
Please advise.
I am not sure I understood it correctly. Can you put all your logic methods in one try-catch? Each call is a separate transaction using TransactionScopeOption.RequiresNew
void DoLogic1(...)
{
try
{
CalculateSomeData(...);
SaveCalculatedData(...);
DoRequestToExternalService(...);
}
catch(Exception ex)
{
LogException(...)
throw;
}
}
But I would like to pass error outside as an exception (to be logged, etc).
Can you use throw?
I've decided to change my 'ExecuteWorker' method to create transaction conditionally. Therefore I'm able to create transaction in the 'DoLogicX' method itself.
精彩评论