We have a handler that performs as supposed to when it's received a message. There are several steps in the process and each consecutive one creates its own, new context, as shown below.
public void Handle(SomeMessage message)
{
...
try
{
...
using(DataContext context = new DataContext()) { ... }
...
using(DataContext context = new DataContext()) { ... }
...
}
catch (Exception exception)
{
...
using(DataContext context = new DataContext()) { ... }
...
}
}
However, on occasion, an exception is thrown and caught in it. The current transaction is rolled back (and since it's not implemented by me explicitly, I'm assuming, without being utterly certain, that it's done by the NServiceBus itself because all the results written to the DB disappear, including those in the catch statement).
At the moment, I'm resolving it by writing to a file when something terrible happens but I'd love to have that stored in the DB as well.
So, ultimately, I'd like to prevent that the last operation, the one in catch statement, is rolled back. Can one do that and if so how?
I'd really like to know the bigger issue, what are you trying to achieve? Why do you want to log something to the database when an error occurs? If it's technical related, the messages should start appearing in the error queue, you should fix the error and have NServiceBus retry the messages. When it's business related, you should have an alternate route to handle the specific business requirement. For example you're out of stock of a specific item, then it might be better to email the buyer to wait for their item or tell them they can get their money back. And inform sales that someone bought an item out of stock, or something like it.
NServiceBus does rollback all transactions, but this is a TransactionScope
related issue. Start a new TransactionScope
and tell it to be a new root transaction.
using(TransactionScope scope1 = new TransactionScope())
//Default is Required
{
using(TransactionScope scope2 = new
TransactionScope(TransactionScopeOption.Required))
{
...
}
using(TransactionScope scope3 = new TransactionScope(TransactionScopeOption.RequiresNew))
{
...
}
using(TransactionScope scope4 = new
TransactionScope(TransactionScopeOption.Suppress))
{
...
}
}
The scope3 transaction is a transaction on its own. If you want, put this inside your catch scope.
This article explains it all. But again, I'd rather have more information on what you're actually trying to achieve. And perhaps read up on this article.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments