前面反复提到,SAP函数的table参数可以作为输入参数(importing parameter), 也可以作为输出参数(exporting paramter)。我们结合具体的例子来看看NCo3.0处理的要点。
将IRfcTable转换成DataTable
很多时候,SAP通过table参数提供返回值,table具有行列这样的结构,为了方便使用,我们将table(类型为IRfcTable,对应的meta-data类型为RfcTableMetaData)转换成Ado.net的DataTable。
public static DataTable ToDataTable(IRfcTable itab)
{
// purpose: convert IRfcTable to DataTable
DataTable dataTable = new DataTable();
// dataTable column definition
for (int i = 0; i < itab.ElementCount; i++) {
RfcElementMetadata metadata = itab.GetElementMetadata(i);
dataTable.Columns.Add(metadata.Name);
}
// line items
for (int rowIdx = 0; rowIdx < itab.RowCount; rowIdx++) {
DataRow dRow = dataTable.NewRow();
// each line is a structure
for (int idx = 0; idx < itab.ElementCount; idx++) {
dRow[idx] = itab[rowIdx].GetObject(idx);
}
dataTable.Rows.Add(dRow);
}
return dataTable;
}
要点讲解
- DataTable的表头从meta-data从获取,每一个元素(element)通过
GetElementMetaData方法获取。通过查看Object Browser,可以看到GetElementMetaData方法可以通过element name来获取,也可以通过element index来获取:
RfcElementMetadata GetElementMetadata(int index);
RfcElementMetadata GetElementMetadata(string name);
为了具有一般性,我们使用index。
- IRfcTable包括多行,每一行都是一个IRfcStructure。刚才的代码通过双重循环,将每一行每一列的数据读取到DataTable中。因为IRfcTable继承自IEnumerable接口,具有iteration功能,所以ToDataTable方法也可以改写为:
public static DataTable ToDataTable(IRfcTable itab)
{
// purpose: convert IRfcTable to DataTable
DataTable dataTable = new DataTable();
// dataTable column definition
for (int i = 0; i < itab.ElementCount; i++) {
RfcElementMetadata metadata = itab.GetElementMetadata(i);
dataTable.Columns.Add(metadata.Name);
}
// line items
foreach (IRfcStructure currenRow in itab) {
DataRow dRow = dataTable.NewRow();
for (int idx = 0; idx < currenRow.ElementCount; idx++) {
dRow[idx] = currenRow.GetObject(idx);
}
dataTable.Rows.Add(dRow);
}
return dataTable;
}
- SAP获取table中某个获取element值,可以有以下写法:
itab[rowIdx].GetObject(idx); // using IRfcContainer.GetObject()
// or
itab[rowIdx][colIdx].GetObject(); // using IRfcElement.GetObject()
// or
itab[rowIdx]["columnName"].GetObject();
另外,对于不同的类型,nco3.0接口提供了不同的Get方法。比如GetString(), GetInt()等等。
完整代码:
Utils.cs
using SAP.Middleware.Connector;
using System.Data;
namespace NCo03
{
public class Utils
{
public static DataTable ToDataTable(IRfcTable itab)
{
// purpose: convert IRfcTable to DataTable
DataTable dataTable = new DataTable();
// dataTable column definition
for (int i = 0; i < itab.ElementCount; i++) {
RfcElementMetadata metadata = itab.GetElementMetadata(i);
dataTable.Columns.Add(metadata.Name);
}
// line items
for (int rowIdx = 0; rowIdx < itab.RowCount; rowIdx++) {
DataRow dRow = dataTable.NewRow();
// each line is a structure
for (int idx = 0; idx < itab.ElementCount; idx++) {
dRow[idx] = itab[rowIdx].GetObject(idx);
}
dataTable.Rows.Add(dRow);
}
return dataTable;
}
public static void PrintDataTable(DataTable dataTable)
{
// purpose: print data table in console
foreach (DataRow row in dataTable.Rows) {
foreach (DataColumn col in dataTable.Columns) {
System.Console.Write(row[col].ToString() + "\t");
}
System.Console.WriteLine();
}
}
}
}
TableManipulation.cs
/**
* Author: Stone Wang(stone.wangmin@qq.com)
* Date: 2016/3/26
*/
using SAP.Middleware.Connector;
using NCo02;
using System.Data;
namespace NCo03
{
public class TableManipulation
{
public DataTable GetCocdList()
{
// method purpose: get company code list from SAP system
DataTable cocdDataTable = null;
RfcDestination dest = DestinationProvider.GetDestination();
IRfcFunction fm = dest.Repository.CreateFunction("BAPI_COMPANYCODE_GETLIST");
fm.Invoke(dest);
IRfcTable cocdRfcTable = fm.GetTable("COMPANYCODE_LIST");
cocdDataTable = Utils.ToDataTable(cocdRfcTable);
return cocdDataTable;
}
}
}
单元测试
TestTableManipulation.cs
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Data;
using NCo03;
namespace UnitTestProject1
{
[TestClass]
public class TestTableManipulation
{
[TestMethod]
public void Test_GetCocdList()
{
TableManipulation rfc = new TableManipulation();
DataTable cocdList = rfc.GetCocdList();
Utils.PrintDataTable(cocdList);
}
}
}