-->

Occasional System.ArgumentNullException using Tran

2019-04-15 01:39发布

问题:

I'm occasionaly getting this exception on our production server:

System.ArgumentNullException: Value cannot be null.
   at System.Threading.Monitor.Enter(Object obj)
   at System.Data.ProviderBase.DbConnectionPool.TransactedConnectionPool.TransactionEnded(Transaction transaction, DbConnectionInternal transactedObject)
   at System.Data.SqlClient.SqlDelegatedTransaction.SinglePhaseCommit(SinglePhaseEnlistment enlistment)
   at System.Transactions.TransactionStateDelegatedCommitting.EnterState(InternalTransaction tx)
   at System.Transactions.CommittableTransaction.Commit()
   at System.Transactions.TransactionScope.InternalDispose()
   at System.Transactions.TransactionScope.Dispose()
   //... continues here with references to my DAL code

What is the reason for this exception to happen?

I have already did some research on this but with no conrete success yet. I also read this questions here:

  • Intermittent System.ArgumentNullException using TransactionScope
  • TransactionScope automatically escalating to MSDTC on some machines?

And now I know that if I could avoid escalating my transactions to DTC I would get rid of this problem. But what if I could not? I have multiple databases to update or read from in one transaction so I have to use DTC. I'm getting this error ocassionaly on actions that usually works well.

Technical background

  • It is ASP MVC2 and LINQ2SQL application on .NET 3.5
  • We have three virtuals with load balanacing based on IP address, each having IIS7
  • Single virutal with SQL server 2008 - it is shared by web servers

I should point out that I was not able to reproduce this exception on my development machine (development server + SQL express 2008) and on our testing machine (virtual with single IIS7 and SQL server 2008 together) either.

I'm suspecting our production servers configuration that there is some threading/processing issue (like two processes are trying to use the same connection).

UPDATE

I have found another link. It is stating that ado.net connection dispose bug is probably back. But it is a pity there is no resolution in the end and I have found nobody else describing similar issue.

  • http://social.msdn.microsoft.com/Forums/nl-BE/adodotnetdataproviders/thread/388a7965-9385-4f5c-a261-1894aa73c16e

回答1:

According to http://support.microsoft.com/kb/960754, there is an issue with 2.50727.4016 version of System.Data.dll.

If your server has this older version, I would try to get the updated one from Microsoft.



回答2:

It looks like a bug, as it's .NET internal code, nothing do do with your own code.

If you take a look with reflector (or any other IL tool) on the internal TransactedConnectionPool.TransactionEnded method, you will see its implementation has changed between .NET 3 and .NET 4... I suppose it was not thread-safe back then. You could try to report it to Microsoft Connect.



回答3:

According to the doco MSDN System.Transactions.TransactionScope the method is synchronous and therefore it's using the monitor. The doco doesn't say that the method is threadsafe, so I think it's likely that you are somehow calling dispose on the same Transaction scope object from more than one thread. You can use a static property of the transactionscope object System.Transactions.Transaction.Current to find out which transaction you are referring to. Perhaps a log message prior to disposing your transaction scope might expose where this is occurring...

If it's not a threading issue then odds on you've found a corner case that trips a bug in .Net. I've found the behaviour of MSDTC when things go wrong to be unpleasant at best.