C# SAP .net 连接器未返回与 SAP GUI 中相同的数据

C# SAP .net connector not returning the same data as seen in SAP GUI

我已遵循此网站上显示的代码:“https://www.veonconsulting.com/integrating-sap-using-nco/”,

我正在尝试从函数 BAPI_PRODORD_GET_DETAIL 获取数据,我在 SAP GUI 上测试了 <bapi_prodord_get_detail><number>1000262</number><struct><order_objects><header>X</header><operations>X</operations><components>X</components></order_objects></struct></bapi_prodord_get_detail>,我可以看到 Header、组件和操作的数据,但是在代码,我没有得到相同的响应,请你帮忙。

代码:

public bool testConnection()
{
  bool state = false;
  string rfcRequest = "<RFC_READ_TABLE><QUERY_TABLE>MARD</QUERY_TABLE><DELIMITER>*"
    + "</DELIMITER><ROWSKIPS>0</ROWSKIPS><ROWCOUNT>0</ROWCOUNT><TABLE><OPTIONS><ROW>"
    + "<TEXT>MATNR IN (</TEXT></ROW><ROW><TEXT>'testConnection'</TEXT></ROW><ROW>"
    + "<TEXT>)</TEXT></ROW></OPTIONS></TABLE></RFC_READ_TABLE>";

  Utils.RfcClient client = new Utils.RfcClient();
  try
  {
    XElement response = client.PullRequestToSAPrfc(rfcRequest);
    state = true;
  }
  catch (RfcLogonException ex)
  {
    Console.Write("Logon Failed");
  }
  catch (RfcInvalidStateException ex)
  {
    Console.Write("RFC Failed");
  }
  catch (RfcBaseException ex)
  {
    Console.WriteLine("communication error" + ex.Message);
  }
  catch (Exception ex)
  {
    Console.Write("Connection error");
  }
  finally
  {
    //client.disconnectDestination();
  }
  return state;
}

public bool testConnection()
{
  bool state = false;
  string rfcRequest = "<bapi_prodord_get_detail><number>1000262</number><struct>"
    + "<order_objects><header>X</header><operations>X</operations><components>X"
    + "</components></order_objects></struct></bapi_prodord_get_detail>";

  Utils.RfcClient client = new Utils.RfcClient();
  try
  {
    XElement response = client.PullRequestToSAPrfc(rfcRequest);
    state = true;
  }
  catch (RfcLogonException ex)
  {
    Console.Write("Logon Failed");
  }
  catch (RfcInvalidStateException ex)
  {
    Console.Write("RFC Failed");
  }
  catch (RfcBaseException ex)
  {
    Console.WriteLine("communication error" + ex.Message);
  }
  catch (Exception ex)
  {
    Console.Write("Connection error");
  }
  finally
  {
    //client.disconnectDestination();
  }
  return state;
}

public XElement PullRequestToSAPrfc(string XMLRequest)
{
  IRfcFunction requestFn;
  requestFn = PrepareRfcFunctionFromXML(XElement.Parse(XMLRequest));

  RfcSessionManager.BeginContext(_ECCsystem);
  requestFn.Invoke(_ECCsystem);
  RfcSessionManager.EndContext(_ECCsystem);

  XElement XMLResponse = PrepareXMLFromrfc(requestFn);

  return XMLResponse;
}

public IRfcFunction PrepareRfcFunctionFromXML(XElement xmlFunction)
{
  RfcRepository repo = _ECCsystem.Repository;
  IRfcFunction RfcFunction = repo.CreateFunction(xmlFunction.Name.ToString());
  foreach (XElement xelement in xmlFunction.Elements())
  {
    if (xelement.Name.ToString().Equals("TABLE"))
    {
      if (NotProcessSpecialTable(xelement))
        continue;
      IRfcTable options = RfcFunction.GetTable(xelement.Descendants().First().Name.ToString());
      foreach (XElement row in xelement.Elements().First().Elements())
      {
        options.Append();
        foreach (XElement rowElement in row.Elements())
        {
          string elementName = rowElement.Name.ToString();
          RfcElementMetadata elementMeta = options.GetElementMetadata(elementName);
          var elementValue = getValueAsMetadata(ref elementMeta, rowElement.Value);
          if (elementValue is string && string.IsNullOrEmpty((string)elementValue)) { continue; }
          options.SetValue(elementName, elementValue);
        }
      }
    }
    else if (xelement.Name.ToString().Equals("STRUCT"))
    {
      IRfcStructure options = RfcFunction.GetStructure(xelement.Descendants().First().Name.ToString());
      foreach (XElement structElement in xelement.Elements().First().Elements())
      {
        string elementName = structElement.Name.ToString();
        RfcElementMetadata elementMeta = options.GetElementMetadata(elementName);
        var elementValue = getValueAsMetadata(ref elementMeta, structElement.Value);
        if (elementValue is string && string.IsNullOrEmpty((string)elementValue)) { continue; }
        options.SetValue(elementName, elementValue);
      }
    }
    else
    {
      string elementName = xelement.Name.ToString();
      RfcElementMetadata elementMeta = RfcFunction.GetElementMetadata(elementName);
      var elementValue = getValueAsMetadata(ref elementMeta, xelement.Value);
      if (elementValue is string && string.IsNullOrEmpty((string)elementValue)) { continue; }
      RfcFunction.SetValue(elementName, elementValue);
    }
  }
  return RfcFunction;
}

public XElement PrepareXMLFromrfc(IRfcFunction rfcFunction)
{
  var XMLRoot = new XElement(rfcFunction.Metadata.Name);
  for (int functionIndex = 0; functionIndex < rfcFunction.ElementCount; functionIndex++)
  {
    var functionMatadata = rfcFunction.GetElementMetadata(functionIndex);
    if (functionMatadata.DataType == RfcDataType.TABLE)
    {
      var rfcTable = rfcFunction.GetTable(functionMatadata.Name);
      var XMLTable = new XElement(functionMatadata.Name);
      foreach (IRfcStructure rfcStracture in rfcTable)
      {
        XElement XMLRow = new XElement("ROW");
        for (int i = 0; i < rfcStracture.ElementCount; i++)
        {
          RfcElementMetadata rfcElementMetadata = rfcStracture.GetElementMetadata(i);
          if (rfcElementMetadata.DataType == RfcDataType.BCD)
          { XMLRow.Add(new XElement(rfcElementMetadata.Name, rfcStracture.GetString(rfcElementMetadata.Name))); }
          else
          {
            XMLRow.Add(new XElement(rfcElementMetadata.Name, rfcStracture.GetString(rfcElementMetadata.Name)));
          }
        }

        XMLTable.Add(XMLRow);
      }
      XMLRoot.Add(XMLTable);
    }
    else if (functionMatadata.DataType == RfcDataType.STRUCTURE)
    {
      var rfcStructure = rfcFunction.GetStructure(functionMatadata.Name);
      XElement XMLRow = new XElement(functionMatadata.Name);
      for (int elementIndex = 0; elementIndex < rfcStructure.ElementCount; elementIndex++)
      {
        RfcElementMetadata eleMeta = rfcStructure.GetElementMetadata(elementIndex);
        XMLRow.Add(new XElement(eleMeta.Name, rfcStructure.GetString(eleMeta.Name)));
      }
      XMLRoot.Add(XMLRow);
    }
    else
    {
      RfcElementMetadata rfcElement = rfcFunction.GetElementMetadata(functionIndex);
      XMLRoot.Add(new XElement(rfcElement.Name, rfcFunction.GetString(rfcElement.Name)));
    }
  }
  return XMLRoot;
}

# Below function is used for the data types.

private object getValueAsMetadata(ref RfcElementMetadata elementMeta, string value)
{
  switch (elementMeta.DataType)
  {
    case RfcDataType.BCD:
      return value;
    case RfcDataType.NUM:
      if (value.Contains("."))
      {
        int elementValue;
        int.TryParse(value, out elementValue);
        return elementValue;
      }
      else
      {
        return Convert.ToInt32(value);
      }
    case RfcDataType.INT1:
      return Convert.ToInt32(value);
    case RfcDataType.INT2:
      return Convert.ToInt32(value);
    case RfcDataType.INT4:
      return Convert.ToInt32(value);
    case RfcDataType.INT8:
      return Convert.ToInt64(value);
    case RfcDataType.CHAR:
      return value;
    case RfcDataType.DATE:
      return DateTime.ParseExact(value, "yyyy-MM-dd", CultureInfo.InvariantCulture);


    default:
      return string.Empty;
  }
}

您遇到了 SAP 中外部和内部价值的经典问题。

您的屏幕截图显示了 SAP 系统中的 ABAP 功能模块测试屏幕。当您在屏幕中输入一个值时,它可能会在调用功能模块之前在内部进行转换。

这些被称为外部和内部格式。 “外部”是用户界面中显示的内容(键入或显示),“内部”是写入数据库的值。

例如,想象一个数据库对象,它的主键是一个 GUID,这是内部格式的对象键,但在用户界面中,这个对象总是通过它的名字(候选键)来引用或显示。

在您的具体情况下,当生产订单是数字时,内部格式始终包含 12 位数字的前导零,外部格式不显示它们。在 Function Module Test 屏幕中,如果您输入此 external 值:

1000262

它被转换为以下内部值,并用它调用 BAPI:

000001000262

一般来说,当您从另一个程序调用任何功能模块时,您必须指明内部值,因为两者之间没有隐含的用户界面。

即,在您的方法中使用此 XML testConnection:

  string rfcRequest = "<bapi_prodord_get_detail><number>000001000262</number><struct>"
    + "<order_objects><header>X</header><operations>X</operations><components>X"
    + "</components></order_objects></struct></bapi_prodord_get_detail>";

另请参阅有关外部和内部格式的回答:

如果您想以编程方式进行所需的字段转换,这在 Sandra Rossi 的回答中有解释,您可以使用 RFM BAPI_CONVERSION_EXT2INT、BAPI_CONVERSION_EXT2INT1、BAPI_CONVERSION_INT2EXT 和 BAPI_CONVERSION_INT2EXT1 这样做。 但是,每个额外的 RFC 调用当然会对性能产生负面影响。

此外,SAP Note 206068 是一个很好的资源,可以解释您也介入的一些 RFC BAPI 陷阱。