Reputation: 951
I get an exception when I try to save an entity inside a TransactionScope
, the exception I get is:
The operation is not valid for the state of the transaction
However on another machine I get a different exception on the same code block:
The transaction operation cannot be performed because there are pending requests working on this transaction
The transaction implementation in my method is:
TransactionHelper.Transaction(() =>
{
if (sys.WfId.HasValue)
{
var sysData = GeneralMapping.GetSysData(model, ThisUser);
DoAction(sys, model, sysData);
if (!_sysClosed)
{
_Repository.InsertOrUpdate(sys);
_Uow.Save();
}
}
});
TransactionHelper:
public static class TransactionHelper
{
public static void HandleTransaction(Action action)
{
using (var tx = CreateScope())
{
action();
tx.Complete();
}
}
private static TransactionScope CreateScope(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted)
{
var tOptions = new TransactionOptions
{
IsolationLevel = isolationLevel,
Timeout = TransactionManager.MaximumTimeout
};
return new TransactionScope(TransactionScopeOption.Required, tOptions);
}
}
This was working perfectly well without any problem, however recently after I started to see these exceptions, I have been told that this implementation might lead into a deadlocks, as the unit of work is a transaction (Business Transaction - Martin Fowler) inside a transaction scope, is that possible to be the reason? and if so, what can be the alternative implementation if needed?
Upvotes: 3
Views: 2664
Reputation: 11554
This exception occurred by several reasons like transaction timeout, nesting two transactions inside each other, two open connection inside of transaction scope, using single DbContext
instance for entire web application and hence DbContext has it's own UOF, it may some conflict occurs between theme for some reason. You can use System.Transactions.Transaction.Current.TransactionInformation.Status
for identifying status of transaction and it my aborted before exception thrown.
Change return new TransactionScope(TransactionScopeOption.Required, tOptions);
to return new TransactionScope(TransactionScopeOption.RequiresNew, tOptions);
and test it again and see what happen.
Upvotes: 1