我有一个使用 ClickOnce 技术部署的 Windows 窗体应用程序 (.NET 3.5),大约有 50-100 个并发用户使用。它们都针对外部托管的同一个 MS SQL 数据库 (SQL SERVER 2008 R2)。
应用程序本身使用“包装器”类来执行数据库查询。此类派生自ServicedComponent并使用[AutoComplete]属性装饰其方法。下面是一个例子:
[Serializable]
[Transaction(TransactionOption.Required, Isolation=TransactionIsolationLevel.ReadCommitted)]
public class CTxGreenfee374Processor: ServicedComponent
{
public CTxGreenfee374Processor() { }
[AutoComplete]
internal Season SaveSeason(CallContext callContext, Season season)
{
return new PGreenfee374Processor().SaveSeason(callContext, season);
}
}
大多数时候,这种方法就像一种魅力。但是当这个方法被调用时,每天会发生很多次异常(当然有类似的方法有这个确切的问题):
System.ArgumentNullException
Value cannot be null.
Server stack trace:
at System.Threading.Monitor.Enter(Object obj)
at System.Data.ProviderBase.DbConnectionPool.TransactedConnectionPool.TransactionEnded(Transaction transaction, DbConnectionInternal transactedObject)
at System.Data.ProviderBase.DbConnectionPool.TransactionEnded(Transaction transaction, DbConnectionInternal transactedObject)
at System.Data.ProviderBase.DbConnectionInternal.CleanupConnectionOnTransactionCompletion(Transaction transaction)
at System.Data.SqlClient.SqlDelegatedTransaction.SinglePhaseCommit(SinglePhaseEnlistment enlistment)
at System.Transactions.TransactionStateDelegatedCommitting.EnterState(InternalTransaction tx)
at System.Transactions.TransactionStateDelegated.BeginCommit(InternalTransaction tx, Boolean asyncCommit, AsyncCallback asyncCallback, Object asyncState)
at System.Transactions.CommittableTransaction.Commit()
at System.EnterpriseServices.TransactionProxy.Commit(Guid guid)
at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
at System.EnterpriseServices.Thunk.Callback.DoCallback(Object otp, IMessage msg, IntPtr ctx, Boolean fIsAutoDone, MemberInfo mb, Boolean bHasGit)
at System.EnterpriseServices.ServicedComponentProxy.CrossCtxInvoke(IMessage reqMsg)
at System.EnterpriseServices.ServicedComponentProxy.Invoke(IMessage request)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at GOLFIT.BusinessProcess.Economics.CTxGreenfee374Processor.SaveSeason(CallContext callContext, Season season)
at GOLFIT.BusinessProcess.Economics.Greenfee374Processor.SaveSeason(CallContext callContext, Season season) in C:\Projekt\GOLFIT\DEVELOPMENTPROD374\BusinessProcess\GOLFIT.BusinessProcess.Economics\Greenfee374\Greenfee374Processor.cs:line 104
at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs)
at System.Runtime.Remoting.Messaging.StackBuilderSink.PrivateProcessMessage(RuntimeMethodHandle md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs)
at System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg, Int32 methodPtr, Boolean fExecuteInContext)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at GOLFIT.BusinessProcess.Economics.Greenfee374Processor.SaveSeason(CallContext callContext, Season season)
at GOLFIT.WinGUI.Economics.FrmPrice374.Save(Boolean refresh).
如您所见,异常中提到了CTxGreenfee374Processor类中的方法SaveSeason 。据我所知,这是我写的最后一段代码。
我唯一的线索是异常与[AutoComplete]属性和/或派生的ServicedComponent类有关。这个结论是基于我检查了无效的输入参数并且在异常之前没有执行方法内的代码。我假设ServicedComponent类和[AutoComplete]属性在方法块执行之前执行某种逻辑。
由于此异常的偶然发生,我在调试时未能成功重新创建此异常。所以我不得不依赖生产应用程序的日志。
如果有人对这个问题有任何想法,将不胜感激!