I've been using Spring.NET's declarative transactions in a web app for some time without issue. Transaction advice is being applied exclusively to service layer methods.
We recently deployed two WCF services that use our Spring managed service objects as dependencies. We are using the Spring.ServiceModel.Activation.ServiceHostFactory
to instantiate these services per the Spring.NET samples.
Shortly after deploying these services to production, we've experienced intermittent errors from the AdoPlatformTransactionManager
class which manages Spring's transactions.
The error text is:
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'Transaction'.
at System.Transactions.Transaction.get_IsolationLevel()
at System.Transactions.TransactionScope..ctor(TransactionScopeOption scopeOption, TransactionOptions
at AdoPlatformTransactionManager.DoBegin(Object transaction, ITransactionDefinition definition)
at Spring.Transaction.Support.AbstractPlatformTransactionManager.GetTransaction(ITransactionDefinition definition)
These errors are intermittent and seem correlated to the current server load (more users = higher likelihood of repro). Additionally, we have not seen such exceptions in any of our non-WCF initiated service method calls. So far, I have two very shaky theories to go on:
- WCF object instancing/scope (PerCall) doesn't play well with singleton service objects
- Some sort of concurrency issue in which multiple WCF service instances are able to interfere with the ambient transaction of other unrelated instances (thread local storage?)
Googling this error and searching the mostly deserted Spring.NET support forums had yielded nothing, so any help or ideas is appreciated!
Update 1
Did a little more debugging and got more clarity around the issue. It appears that the real problem is not transaction related but instead about recovering WCF channels from a faulted state.
Any time an unhandled exception is being thrown during a WCF method call (in my case it was FK violation), the channel appears to be left in a permanently faulted state.
To make matters worse, once a channel goes to a faulted state, it affect all users of that service since Spring.NET doesn't create a new channel for each user. The only way to resolve the issue appears to be to recycle the Application Pool.
Based on the referenced links below, I'm not sure whether the problem is in Spring.NET, WCF faulting in general or something else entirely.
References
client-timeout-when-using-wcf-through-spring-net
Best-Practices-and-Recover-a-Faulted-Channel
what-is-the-best-workaround-for-the-wcf-client-using-block-issue