SAP .NET Connector: 在封送 .NET 类型时引发系统异常

3
我的应用程序向SAP发送大量的数据。为了做到这一点,它会构建一个SAP表对象并将其发送过去。我经常遇到这个错误,但并不总是可靠的:
System exception thrown while marshaling .NET type 20081219 to RFCTYPE_BCD
   at SAP.Connector.Rfc.RfcMarshal.NetFieldToRfcField(Object src, RFCTYPE type, Encoding encoding, Byte[] dest, Int32 offset, Int32 len, Int32 charSize, Int32 decimals)
   at SAP.Connector.Rfc.RfcStructureUtil.ToRfcStructure(Object obj, Byte[] dest, Type t, Encoding encoding, Boolean isUnicode, PropertyInfo[] propinfos, RfcStructInfo structInfo)
   at SAP.Connector.Rfc.RfcStructureUtil.GetITabFromList(SAPConnection conn, Object list, Type t, RfcStructInfo structInfo, Int32 itab)
   at SAP.Connector.Rfc.RfcClient.PrepareClientParameters(Type classType, MethodInfo m, Boolean isTQRfc, Object[] MethodParamsIn, RFC_PARAMETER[]& paramsIn, RFC_PARAMETER[]& paramsOut, RFC_TABLE[]& tables, ParameterMap[]& paramMaps)
   at SAP.Connector.Rfc.RfcClient.RfcInvoke(SAPClient proxy, String method, Object[] methodParamsIn)
   at SAP.Connector.SAPClient.SAPInvoke(String method, Object[] methodParamsIn)
奇怪的是,这种情况并不是每次都发生。此外,它抱怨的.NET类型“20081219”是我传递的数据(一个日期)--而不是一种类型。我认为该字段的类型是RFCTYPE.RFCTYPE_TIME
有关如何排除这个间歇性错误的建议吗?在调用SAP RFC之间是否应该清除某种状态?
更新:
根据要求,这是调用SAP的代码:
Using sapConnection As New MySapProxy(ConnectionString)
  sapConnection.Connection.Open()
  sapConnection.TheSapRfcICall(SapOpCode, Nothing, Nothing, sapTable, ResultTable)
End Using

我在想可能是多个线程以某种方式使用了同一个连接。但是改用 SAP.Connector.GetNewConnection 并没有改变任何事情。

更新:

看起来即使我只运行一个线程,这个问题仍然会发生!怎么回事?

有没有办法禁用连接池来看看是否能解决这个问题?


更新:
@Igal Serban的回答似乎对我有效。明天早上我会检查日志并(希望能够)颁发奖金!非常感谢。
更新:
根据要求,我使用的librfc32.dll版本是6403.3.78.4732。
4个回答

1

编辑:

我仍然认为这与映射有关。我相信RFCTYPE_BCD类型是十进制数(Business Connector Decimal),因此将日期值推送到其中可能会有困难(并且有时可能会起作用?)。我建议重新生成代理,或在出现错误时记录被编组的数据。像这样(抱歉-我们使用自己的代理层,所以我对Business Connector不是很熟悉):

您能将以下内容翻译成VB(以及sapTable结构的格式)吗?

Using sapConnection As New MySapProxy(ConnectionString)
  sapConnection.Connection.Open()
  try {
    sapConnection.TheSapRfcICall(SapOpCode, Nothing, Nothing, sapTable, ResultTable)
  } catch (Exception e) {
    StringBuilder sb = new StringBuilder();
    foreach (Field f in sapTable.Fields) {
      sb.AppendLine(f.Name + "=" f.Value);
    }
    sb.AppendLine(e.StackTrace);
    File.AppendAllText("C:\\Exception_" + DateTime.Now.ToString("u") + ".txt", sb.ToString());
  }
End Using

我知道这很麻烦,但只需快速而粗略地进行一些操作,以便在出现错误时输出一些数据。

========

从您发布的描述,我最好的猜测是您可能正在尝试将一个日期值(20081219)转换成时间字段?
您能否在try/catch中封装该调用,并记录发送到SAP的表格的值并在此处发布?我希望数据中有线索。
我知道通过Web服务发布到SAP,SAP对其日期时间和值的格式非常特别。

不幸的是,我排除了格式问题,因为这种情况并不一致发生。 - Michael Haren
要准确地说,RFCTYPE_BCD 是用于压缩二进制编码十进制的。 - Sandra Rossi

1

更新4: 经过再次思考,我认为librfc版本并不重要。异常似乎来自托管代码。我能想到的选项是:

  • 尝试在单线程版本上使用调试器。
  • 神奇的方法。即使没有找到错误(这是在sap或您的代码中),只要改变业务方式就可以让它消失。虽然很丑陋,但有时很实用。无论如何,对于您的情况,推荐的方法似乎是使用连接池,而不是为每个请求创建新的代理对象。因此,可以使用类似以下(未经测试)代码:

MySapProxy proxy = new MySapProxy(); // do this only once.

// and in you main loop:
using (proxy.Connection = Connection.GetConnection(connectionString))
{
    proxy.TheSapRfcICall(SapOpCode, Nothing, Nothing, sapTable, ResultTable)
}

这个示例隐式地使用连接池。可以从配置文件中控制使用。

更新3:您能否检查一下librfc32.dll的版本和日期?它应该在system32目录或您的应用程序目录中,或者在您的%path%中的某个位置。

更新2:Sap笔记就像kb文章一样。我不知道在sdn.sap.com上是否有免费访问笔记,所以我已经将其发送到您的邮箱。

更新1:SAP Note 1000057说明:

在多线程重负载下,可能会发生类型为RfcMarshalException的异常,内部异常引用为System.Xml.Xsl.XsltException。

虽然不完全是您收到的异常,但值得一试。

补丁作为附件附加在此说明中。

更新0:只是一个猜测。但我建议查看线程问题。这是全部堆栈吗?您能发布调用sap代码的代码部分吗?


既然你提到了,那就很有道理。我会将应用程序强制降至一个线程,并查看问题是否消失。 - Michael Haren
当只运行单个线程时,它确实会消失。现在我只需要弄清楚为什么... - Michael Haren
@Igal Serban:不幸的是,这并没有解决问题。我认为你的想法是正确的,它似乎在突发情况下发生,可能是在高负载时间内。 - Michael Haren
根据要求,我所使用的librfc32.dll版本是6403.3.78.4732。 - Michael Haren
我同意通过保持长连接来减少连接周期的数量可能会有所帮助,不过了解真正的问题也是很好的。 - Michael Haren

0

看起来它试图将整数或字符串(由于ToString()无法确定)转换为BCD(二进制编码十进制)类型。

只是猜测,希望能有所帮助。

更新:

看来不是这个问题。

多个线程同时使用同一个连接?这可能不是一个很好的主意,除非你使用锁定,这会使线程变得无意义。我相信SAP支持连接池,所以在它自己的线程中打开连接(每个线程一个)。


不,每个线程都有自己的连接。事实上,我已经更改了代码,使得每个线程在需要时都会创建、打开/关闭连接。但这并没有起到帮助作用。 - Michael Haren

0

可能是日期格式的问题吗?你说它不是每次都发生。
所以当你传递20081202时,它将'12'作为日部分和'02'作为月份部分。这没问题。
但是当你传递20081219时,它尝试解析19作为月份并抛出异常?
与你的SAP管理员检查一下。


不幸的是,我排除了格式问题,因为这种情况并不一致。也就是说,它在相同的数据下既可以工作又可以失败。 - Michael Haren

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接