System.InvalidOperationException: The transaction associated with the current connection has completed but has not been disposed. The transaction must be disposed before the connection can be used to execute sql statements.
可能有帮助的东西
大约2周前,我们改变了生产网络数据库服务器.这个错误只有在我们移动之后才会抛出.当我们在旧服务器上时,我从未遇到这个问题.但事情是,这个错误在前9-10天没有发生.现在突然间歇地发生了.我上传了大文件(1k-2.5k行),并且它们工作正常,并且这个错误引发了更小的文件,它们有200行!而且服务有时会完美处理相同的文件.
代码片段:(它大得多,但重复类似的操作)
using (var scope = new TransactionScope()) { // loop through each row/invoice foreach (var row in Rows) { Invoice invoice = (Invoice)CreateObjectWithConstantData(typeof(Invoice),doc,applicationName); invoice = (Invoice)FillObjectWithUserData(invoice,row,-1,string.Empty); invoice.InvoiceNumber = InvoiceDBImpl.SaveInvoice(invoice,processFileRequest.RunId); if (invoice.InvoiceNumber == Guid.Empty) { throw new DataAccessException(string.Format(Messages.ErrorSavingInvoice,invoice.ReceiptId,invoice.ProductID)); } } }
堆栈跟踪之一:
at System.Data.sqlClient.TdsParser.TdsExecuteRPC(_sqlRPC[] rpcArray,Int32 timeout,Boolean inSchema,sqlNotificationRequest notificationRequest,TdsParserStateObject stateObj,Boolean isCommandProc) at System.Data.sqlClient.sqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior,RunBehavior runBehavior,Boolean returnStream,Boolean async) at System.Data.sqlClient.sqlCommand.RunExecuteReader(CommandBehavior cmdBehavior,String method,DbAsyncResult result) at System.Data.sqlClient.sqlCommand.InternalExecuteNonQuery(DbAsyncResult result,String methodName,Boolean sendToPipe) at System.Data.sqlClient.sqlCommand.ExecuteNonQuery() at System.Data.sqlClient.sqlCommand.ExecuteNonQuery() at System.Data.Linq.sqlClient.sqlProvider.Execute(Expression query,QueryInfo queryInfo,IObjectReaderFactory factory,Object[] parentArgs,Object[] userArgs,ICompiledSubQuery[] subQueries,Object lastResult) at System.Data.Linq.sqlClient.sqlProvider.ExecuteAll(Expression query,QueryInfo[] queryInfos,Object[] userArguments,ICompiledSubQuery[] subQueries) at System.Data.Linq.sqlClient.sqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query) at System.Data.Linq.DataContext.ExecuteMethodCall(Object instance,MethodInfo methodInfo,Object[] parameters) at Tavisca.TramsFileService.DataAccess.TramsDBDataContext.SaveTramsPayment(Nullable`1 paymentDate,String paymentType,Nullable`1 totalAmount,String bankAccount,String paymentMethod,String branch,String remarks,String creditCardLast4,String payeeName,String profileNumber,Nullable`1& paymentId) at Tavisca.TramsFileService.DataAccess.PaymentDBImpl.<>c__DisplayClass1.<SavePayment>b__0(TramsDBDataContext dc) at Tavisca.TramsFileService.DataAccess.SystemDataContext.PerformOperation(Action`1 action) at Tavisca.TramsFileService.DataAccess.PaymentDBImpl.SavePayment(Payment payment) at Tavisca.TramsFileService.Core.TramsFileController.ProcessFile(ProcessFileRQ processFileRequest) at Tavisca.TramsFileService.ServiceImplementation.TramsFileServiceImpl.ProcessFile(ProcessFileRQ processFileRequest)
我已经通过一些链接:
他们都建议在machine.config上增加TimeOut,但是我不知道为什么它有时工作,而在其他时间不起作用.这不应该是一致的吗?
解决方法
using (var scope = new TransactionScope()) { //Your stuff goes here scope.Complete(); }
必须使用.Complete()函数在最后一行提交任何事务.
其次,如果增加machine.config上的TimeOut功能,那么这样做并没有什么危害,因为long文件显然需要更多的时间.
第三,确保在TransactionScope中调用的任何其他组件都适用于所有正的&负面情景.通过stacktrace,它似乎特别用于一些打破内部函数Tavisca.TramsFileService.ServiceImplementation.TramsFileServiceImpl.ProcessFile(ProcessFileRQ processFileRequest)
还要确保如果某些存储过程由TransactionScope内的任何底层调用使用,那么存储过程中的任何失败事务也可能导致TransactionScope.
另外一件事,抛出的异常也可能是合法的,因为当你发送invoice.InvoiceNumber == Guid.Empty时手动抛出异常,但是如果它被处理/捕获或者只是传递给上层,则不提及它.
但首先尝试添加scope.Complete();这可能是根本原因.