问题
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.
来源:https://stackoverflow.com/questions/13344778/occasional-system-argumentnullexception-using-transactionscope-and-ms-dtc