I'm working on an application that is multi-threaded and using NServiceBus and NHibernate with SQL Server 2008RC (using DTC). The process has one session factory. Each thread has it's own Session which is disposed of when the transaction is completed. We're intermittently seeing the exception below being thrown, it's happened 5 minutes after starting the process and 6 hours after starting the process. There doesn't seem to be a pattern for when it happens.
It looks like the AbstractBatcher is running into trouble closing commands when the DTC transaction is aborted.
Any help much appreciated.
Framework Version: v4.0.30319 Description: The process was terminated due to an unhandled exception. Exception Info: System.InvalidOperationException Stack: at System.Collections.Generic.Dictionary`2+KeyCollection+Enumerator[[System._Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System._Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].MoveNext() at NHibernate.AdoNet.AbstractBatcher.CloseCommands() at NHibernate.AdoNet.AbstractBatcher.Dispose(Boolean) at NHibernate.Impl.SessionImpl.Close() at NHibernate.Impl.SessionImpl.Dispose(Boolean) at NHibernate.Transaction.AdoNetWithDistributedTransactionFactory+<>c_DisplayClass1.b_0(System.Object, System.Transactions.TransactionEventArgs) at System.Transactions.TransactionCompletedEventHandler.Invoke(System.Object, System.Transactions.TransactionEventArgs) at System.Transactions.TransactionStatePromotedAborted.EnterState(System.Transactions.InternalTransaction) at System.Transactions.InternalTransaction.DistributedTransactionOutcome(System.Transactions.InternalTransaction, System.Transactions.TransactionStatus) at System.Transactions.Oletx.RealOletxTransaction.FireOutcome(System.Transactions.TransactionStatus) at System.Transactions.Oletx.OutcomeEnlistment.InvokeOutcomeFunction(System.Transactions.TransactionStatus) at System.Transactions.Oletx.OletxTransactionManager.ShimNotificationCallback(System.Object, Boolean) at System.Threading._ThreadPoolWaitOrTimerCallback.PerformWaitOrTimerCallback(System.Object, Boolean)