前面反復提到,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);
}
}
}