所以我有一个WCF服务,里面有一个Process()方法。此方法从一个表中读取一个字节数组(一个文件),并且基本上将那个文件中的数据放入多个表中。它只是遍历每一行。从生产环境开始的一个月以来,它一直运行良好。现在突然之间,它间歇性地抛出此错误:



可能有帮助的事情:
大约2周前,我们更换了Production Web和DB服务器。仅在我们移动后才抛出此错误。当我们在旧服务器上时,我从未遇到过此问题。但问题是,此错误在开始的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, -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, RunBehavior runBehavior, Boolean returnStream, 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, IObjectReaderFactory factory, 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)

我已经通过一些链接:
  • Link 1
  • Link 2
  • Link 3

  • 他们都建议增加machine.config上的超时,但是我不确定为什么有时会起作用,而其他时候却不起作用。这不应该是一致的吗?

    最佳答案

    首先,我建议在scope.Complete();的末尾添加TransactionScope,例如:

    using (var scope = new TransactionScope())
    {
         //Your stuff goes here
    
         scope.Complete();
    }
    

    必须使用.Complete()函数在最后一行提交任何事务。

    其次,如果增加TimeOut上的machine.config有效,则这样做没有害处,因为长文件显然需要更多时间。

    第三,确保在TransactionScope内部调用的任何其他组件都适用于所有积极和消极的情况。通过stacktrace,在特定的用例中似乎有些中断了Tavisca.TramsFileService.ServiceImplementation.TramsFileServiceImpl.ProcessFile(ProcessFileRQ processFileRequest)函数

    还要确保TransactionScope内的任何基础调用是否使用了某个存储过程,那么存储过程内的任何失败事务也会导致TransactionScope

    另外一件事,抛出异常也可能是合法的,因为您在invoice.InvoiceNumber == Guid.Empty时手动抛出异常,但是如果处理/捕获或只是将其传递到上层则未提及。

    但是首先尝试添加 scope.Complete(); ,这可能是根本原因。

    10-08 12:34