SAP .NET 连接器:封送 .NET 类型时抛出系统异常

发布于 2024-07-09 21:16:25 字数 1797 浏览 11 评论 0原文

我的应用程序向 SAP 发送大量数据。 为此,它构建一个 SAP 表对象并将其发送出去。 我经常收到此错误,但并不可靠:

将 .NET 类型 20081219 封送至 RFCTYPE_BCD 时引发系统异常 
     在 SAP.Connector.Rfc.RfcMarshal.NetFieldToRfcField(对象 src、RFCTYPE 类型、编码编码、Byte[] dest、Int32 偏移量、Int32 len、Int32 charSize、Int32 小数) 
     在 SAP.Connector.Rfc.RfcStructureUtil.ToRfcStructure(对象 obj、Byte[] dest、类型 t、编码编码、布尔 isUnicode、PropertyInfo[] propinfos、RfcStructInfo structInfo) 
     在 SAP.Connector.Rfc.RfcStructureUtil.GetITabFromList(SAPConnection conn,对象列表,类型 t,RfcStructInfo structInfo,Int32 itab) 
     在 SAP.Connector.Rfc.RfcClient.PrepareClientParameters(Type classType, MethodInfo m, Boolean isTQRfc, Object[] MethodParamsIn, RFC_PARAMETER[]& paramsIn, RFC_PARAMETER[]& paramsOut, RFC_TABLE[]& 表, ParameterMap[]&参数映射) 
     在 SAP.Connector.Rfc.RfcClient.RfcInvoke(SAPClient 代理,字符串方法,Object[] methodParamsIn) 
     在 SAP.Connector.SAPClient.SAPInvoke(字符串方法,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。

My app sends lots and lots of data to SAP. To di this, it builds up an SAP table object and sends it over. I get this error somewhat regularly, but not reliably:

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)

What's weird is that it doesn't happen every time. Also, the .NET type it complains about, "20081219" is the data I'm passing (a date)--not a type. I think the type of that field is RFCTYPE.RFCTYPE_TIME.

Any suggestions on how to troubleshoot this intermittent error? Is there some kind of state I should be clearing between calls to the SAP RFCs?


Update:

As requested, here's the code that calls SAP:

Using sapConnection As New MySapProxy(ConnectionString)
  sapConnection.Connection.Open()
  sapConnection.TheSapRfcICall(SapOpCode, Nothing, Nothing, sapTable, ResultTable)
End Using

I'm thinking maybe multiple threads are using the same connection some how. Using SAP.Connector.GetNewConnection instead didn't change anything.


Update:

It seems this problem occurs even when I run a single thread! What's the deal??

Is there a way to disable the connection pool to see if that fixes it?


Update:

@Igal Serban's answer seems to be working for me. I'll check the logs tomorrow morning and (hopefully) award the bounty! Thanks so much.


Update:

As requested, my version of librfc32.dll is 6403.3.78.4732.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

辞取 2024-07-16 21:16:25

更新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 说明 1000057 指出:

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

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

补丁可作为本说明的附件提供。

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

Update 4: In second thought, I don't think that the librfc version is important. The exception seems to come from the managed code. The options that I can think of are:

  • Try to use debugger on the single threaded version.
  • The magical way. Even without finding the bug ( That is on sap or your code). Just changing the way you do business can make it go away. Its ugly, but sometimes practical. Anyway the recommended way for your scenario seems to be to use connection pool, and not to create new proxy object for each request. So something like this (untested) code can be used:

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)
}

This sample is using implicitly the connection pool. The use of can be controlled from the config file.

Update 3: Can you please check your librfc32.dll version and date? its should be in system32 directory or in your application directory or somewhere in your %path%.

Update 2: Sap notes are just like kb articles. I don't know if there is free access to the note in the sdn.sap.com so I have send it to your mail.

Update 1: SAP Note 1000057 states:

Under multithreaded heavy load, exceptions of type RfcMarshalException with reference to System.Xml.Xsl.XsltException as inner exception may occur.

While not exactly the exception you receive. Its worth a try.

Patch is available as attachment to this note.

**Update 0:**Only a guess. But I would suggest to look at threading issues. Is this all the stack? Can you post the part off the code where you call the sap code?

习ぎ惯性依靠 2024-07-16 21:16:25

编辑

我仍然认为这与映射有关。 我相信 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 的表的值并将其发布到此处? 我希望数据能提供线索。

通过向 SAP 发布 Web 服务,我知道 SAP 对于日期时间和日期的格式非常讲究。 价值观。

Edit:

I still think it's something to do with the mapping. I believe that RFCTYPE_BCD type is decimal (Business Connector Decimal), so it will have difficulty pushing a date value into it (and could possibly work sometimes?). I would suggest regenerating the proxies, or log the data being marshalled when you get the error. Something like this (sorry - we use our own proxy layer, so I'm not that familiar with Business Connector):

Could you translate the following into VB (and whatever the format of the sapTable structure is):

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

I know it's a pain, but just do a quick and dirty to get some data to spit out when the error occurs.

========

From just the description you've posted, the best I can come up with is perhaps you are trying to marshal a date value (20081219) into a time field?

Can you wrap that call in a try/catch and log the values of the table being sent to SAP and post those here? I'm hoping there's a clue in the data.

I know from doing web service postings to SAP that SAP is quite particular about the format of its date time & values.

听不够的曲调 2024-07-16 21:16:25

看起来它正在尝试将整数或字符串(由于 ToString() 而无法区分)转换为 BCD(二进制编码的十进制)类型。

只是一个猜测,希望有帮助。

更新:

猜测不是。

多个线程使用同一个连接? 这可能不是一个好主意,除非您使用锁定,否则线程将变得毫无意义。 我确信 SAP 支持连接池,因此在它自己的线程中打开连接(每个线程一个)。

It looks like it is trying to convert an integer or a string (cant tell due to ToString()) to a BCD (binary-coded decimal) type.

Just a guess, hope it helps.

UPDATE:

Guess not.

Multiple threads using the same connection? That's probably not a very good idea, unless you use locking, which will make the thread pointless. I'm sure SAP supports connection pools, so open the connection in it's own thread (one per thread).

温柔少女心 2024-07-16 21:16:25

可能是日期格式问题? 你说这不会每次都会发生。
因此,当您传递 20081202 时,它将“12”作为日部分,将 02 作为月份部分。 没关系。
但是当你传递 20081219 时,它会尝试将 19 解析为月份并抛出异常?
请与您的 SAP 管理员核实。

May it be the date format issue? You say it doesn't happens every time.
So when you pass 20081202 it takes '12' as a day part and 02 as a month part. It's OK.
But when you pass 20081219 it tries to parse 19 as a month and throws exception?
Check it with your SAP administrator.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文