使用 WCF 服务模型在 SAP 中调用 tRFC
事务性远程函数调用 (tRFC) 保证在 SAP 系统上 一次性 执行 RFC。 可以将 SAP 适配器显示的任何 RFC 作为 tRFC 调用。 在 WCF 服务模型中调用 tRFC 类似于调用 RFC,但存在以下差异:
SAP 适配器在与 RFC (RFC) 不同的节点 (TRFC) 下显示 tRFC。
tRFC 客户端调用不返回 SAP 导出和更改参数的值。
tRFC 操作包括一个 GUID 参数,该参数由 SAP 适配器映射到 tRFC 的 SAP 事务 ID (TID) 。
调用 tRFC 后,必须调用 RfcConfirmTransID 操作以确认 (提交) SAP 系统上的 tRFC。 此操作直接显示在 TRFC 节点下。
有关 tRFC 操作和 RfcConfirmTransID 操作的详细信息,请参阅 SAP 中 tRFC 的操作。
以下部分演示如何使用 SAP 适配器在 SAP 系统上调用 tRFC。
WCF 客户端类
SAP 适配器显示单个服务协定“Trfc”下的所有 tRFC 操作。 这意味着为要调用的所有 tRFC 操作创建单个 WCF 客户端类 TrfcClient。 每个目标 tRFC 表示为此类的方法。 对于每个方法:
复杂的 SAP 类型(如结构)显示为 .NET 类,其属性对应于 SAP 类型的字段。 这些类在以下命名空间中定义: microsoft.lobservices.sap._2007._03.Types.Rfc。
以下代码演示 了 TrfcClient 类的一部分,以及调用 BAPI_SALESORDER_CREATEFROMDAT2 (作为 SAP 系统上的 tRFC) 的方法。 TransactionalRfcOperationIdentifier 参数包含映射到 SAP TID 的 GUID。 不会显示方法的所有参数。
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class TrfcClient : System.ServiceModel.ClientBase<Trfc>, Trfc {
....
/// <summary>The Metadata for this RFC was generated using the RFC SDK.</summary>
public void BAPI_SALESORDER_CREATEFROMDAT2(
string BEHAVE_WHEN_ERROR,
string BINARY_RELATIONSHIPTYPE,
string CONVERT,
string INT_NUMBER_ASSIGNMENT,
microsoft.lobservices.sap._2007._03.Types.Rfc.BAPISDLS LOGIC_SWITCH,
microsoft.lobservices.sap._2007._03.Types.Rfc.BAPISDHD1 ORDER_HEADER_IN,
…
microsoft.lobservices.sap._2007._03.Types.Rfc.BAPIADDR1[] PARTNERADDRESSES,
microsoft.lobservices.sap._2007._03.Types.Rfc.BAPIRET2[] RETURN,
ref System.Guid TransactionalRfcOperationIdentifier) { ... }
}
以下代码显示了为 RfcConfirmTransID 操作生成的 方法。 必须确保此方法作为 TrfcClient 的一部分生成。 RfcConfirmTransID 操作直接显示在 TRFC 节点下。
public void RfcConfirmTransID(System.Guid TransactionalRfcOperationIdentifier) {…}
如何创建 tRFC 客户端应用程序
创建调用 TFC 的应用程序的步骤类似于调用 RFC 的步骤,但以下例外:
必须检索 TRFC 节点下的目标操作。
必须检索 RfcConfirmTransID 操作。 这直接显示在 TRFC 节点下。
若要确认 (提交) SAP 系统上的 tRFC 操作,必须使用为该 tRFC 操作返回的 GUID 调用 RfcConfirmTransID 操作。
创建 tRFC 客户端应用程序
生成 TrfcClient 类。 使用添加适配器服务引用 Visual Studio 插件或 ServiceModel 元数据实用工具 (svcutil.exe) 生成一个面向要使用的 RFC 的 TrfcClient 类。 有关如何生成 WCF 客户端的详细信息,请参阅 为 SAP 解决方案项目生成 WCF 客户端或 WCF 服务协定。 确保 TrfcClient 类中包含 RfcConfirmTransID 操作。
创建步骤 1 中生成的 TrfcClient 类的实例,并指定客户端绑定。 指定客户端绑定涉及指定 TrfcClient 将使用的绑定和终结点地址。 可以在代码中强制执行此操作,也可以在配置中以声明方式执行此操作。 有关如何指定客户端绑定的详细信息,请参阅 为 SAP 系统配置客户端绑定。 以下代码从配置初始化 TrfcClient 并设置 SAP 系统的凭据。
TrfcClient trfcClient = new TrfcClient("SAPBinding_Rfc"); trfcClient.ClientCredentials.UserName.UserName = "YourUserName"; trfcClient.ClientCredentials.UserName.Password = "YourPassword";
打开 TrfcClient。
trfcClient.Open();
在步骤 2 中创建的 TrfcClient 上调用适当的方法,以调用 SAP 系统上的目标 tRFC。 可以传递一个变量,该变量包含 GUID 或包含 事务性RrcOperationIdentifier 参数的空 GUID。 如果传递一个空的 GUID,SAP 适配器将为你生成一个。 以下代码在 SAP 系统上调用BAPI_SALESORDER_CREATEFROMDAT2作为 tRFC, (方法的所有参数都) 显示。 指定了 GUID。
transactionalRfcOperationIdentifier = Guid.NewGuid(); //invoke RFC_CUSTOMER_GET as a tRFC trfcClient.BAPI_SALESORDER_CREATEFROMDAT2( request.BEHAVE_WHEN_ERROR, request.BINARY_RELATIONSHIPTYPE, request.CONVERT, ... ref transactionalRfcOperationIdentifier);
若要确认与 SAP 系统上的 tRFC 关联的 TID,请在 TrfcClient 上调用 RfcConfirmTransID 方法。 为 TransactionRfcOperationIdentifier参数指定步骤 4 中返回的 GUID。
trfcClient.RfcConfirmTransID(transactionalRfcOperationIdentifier);
使用完 TrfcClient 后, (完成调用所有 tRFC) 后将其关闭。
trfcClient.Close();
示例
以下示例演示如何以 tRFC 的形式调用BAPI_SALESORDER_CREATE。
using System;
using System.Collections.Generic;
using System.Text;
// Add WCF, the WCF LOB Adapter SDK, and SAP adapter namepaces
using System.ServiceModel;
using Microsoft.Adapters.SAP;
using Microsoft.ServiceModel.Channels;
// Include this namespace for WCF LOB Adapter SDK and SAP exceptions
using Microsoft.ServiceModel.Channels.Common;
using microsoft.lobservices.sap._2007._03.Types.Rfc;
// This example demonstrates sending BAPI_SALESORDER_CREATEFROMDAT2 as a tRFC. The client has
// methods to:
// send the BAPI (BAPI_SALESORDER_CREATEFROMDAT2)and to
// Confirm the transaction (RfcConfirmTransID)
// An instance of BAPI_SALESORDER_CREATEFROMDAT2Request (generated)
// is used to format the BAPI before invoking BAPI_SALESORDER_CREATEFROMDAT2. This
// is not necessary, but is done to make it easier to read the code.
// tRFC invocations always includes a ref parameter that contains a GUID. You can optionally
// set this parameter when you invoke the method; however, you must use the value returned by
// the adapter when you call RfcConfirmTransID to confirm the transaction on the SAP system.
// You can call the utility method, SAPAdapterUtilities.ConvertGuidToTid, to get the value
// of the SAP transaction Id from the GUID that the adapter returns.
namespace SapTrfcClientSM
{
class Program
{
static void Main(string[] args)
{
TrfcClient sapTrfcClient = null;
try
{
Console.WriteLine("SAP TRFC client sample started");
Console.WriteLine("Creating the TRFC client");
// Create the SAP Trfc Client from configuration
sapTrfcClient = new TrfcClient("SAPBinding_Trfc");
sapTrfcClient.ClientCredentials.UserName.UserName = "YourUserName";
sapTrfcClient.ClientCredentials.UserName.Password = "YourPassword";
Console.WriteLine("Opening the TRFC client");
// Open the Trfc Client
sapTrfcClient.Open();
// Create a GUID -- note: this is optional. If you do not pass a GUID,
// for the TransactionalRfcOperationIdentifier parameter, the SAP adapter will
// generate one, associate it with the SAP TID, and set the
// TransactionalRfcOperationIdentifier parameter.
Guid tidGuid = Guid.NewGuid();
BAPI_SALESORDER_CREATEFROMDAT2Request request = new BAPI_SALESORDER_CREATEFROMDAT2Request();
request.ORDER_HEADER_IN = new BAPISDHD1();
request.ORDER_HEADER_IN.DOC_TYPE = "TA";
request.ORDER_HEADER_IN.SALES_ORG = "1000";
request.ORDER_HEADER_IN.DISTR_CHAN = "10";
request.ORDER_HEADER_IN.DIVISION = "00";
request.ORDER_HEADER_IN.SALES_OFF = "1000";
request.ORDER_HEADER_IN.REQ_DATE_H = DateTime.Now;
request.ORDER_HEADER_IN.PURCH_DATE = DateTime.Now;
request.ORDER_HEADER_IN.PURCH_NO_C = "Cust PO";
request.ORDER_HEADER_IN.CURRENCY = "EUR";
BAPISDITM[] orderItems = new BAPISDITM[1];
orderItems[0] = new BAPISDITM();
orderItems[0].MATERIAL = "P-109";
orderItems[0].PLANT = "1000";
orderItems[0].TARGET_QU = "ST";
request.ORDER_ITEMS_IN = orderItems;
BAPIPARNR[] orderPartners = new BAPIPARNR[1];
orderPartners[0] = new microsoft.lobservices.sap._2007._03.Types.Rfc.BAPIPARNR();
orderPartners[0].PARTN_ROLE = "AG";
orderPartners[0].PARTN_NUMB = "0000001390";
request.ORDER_PARTNERS = orderPartners;
// Create a GUID -- note: this is optional. If you do not pass a GUID,
// for the TransactionalRfcOperationIdentifier parameter, the SAP adapter will
// generate one, associate it with the SAP TID, and set the
// TransactionalRfcOperationIdentifier parameter.
request.TransactionalRfcOperationIdentifier = Guid.NewGuid();
Console.WriteLine("Invoking BAPI_SALESORDER_CREATEFROMDAT2 as a tRFC");
//invoke RFC_CUSTOMER_GET as a tRFC
sapTrfcClient.BAPI_SALESORDER_CREATEFROMDAT2(request.BEHAVE_WHEN_ERROR,
request.BINARY_RELATIONSHIPTYPE,
request.CONVERT,
request.INT_NUMBER_ASSIGNMENT,
request.LOGIC_SWITCH,
request.ORDER_HEADER_IN,
request.ORDER_HEADER_INX,
request.SALESDOCUMENTIN,
request.SENDER,
request.TESTRUN,
request.EXTENSIONIN,
request.ORDER_CCARD,
request.ORDER_CFGS_BLOB,
request.ORDER_CFGS_INST,
request.ORDER_CFGS_PART_OF,
request.ORDER_CFGS_REF,
request.ORDER_CFGS_REFINST,
request.ORDER_CFGS_VALUE,
request.ORDER_CFGS_VK,
request.ORDER_CONDITIONS_IN,
request.ORDER_CONDITIONS_INX,
request.ORDER_ITEMS_IN,
request.ORDER_ITEMS_INX,
request.ORDER_KEYS,
request.ORDER_PARTNERS,
request.ORDER_SCHEDULES_IN,
request.ORDER_SCHEDULES_INX,
request.ORDER_TEXT,
request.PARTNERADDRESSES,
request.RETURN,
ref request.TransactionalRfcOperationIdentifier);
string sapTxId = null;
sapTxId = SAPAdapterUtilities.ConvertGuidToTid(request.TransactionalRfcOperationIdentifier);
Console.WriteLine("BAPI_SALESORDER_CREATEFROMDAT2 Sent");
Console.WriteLine("The SAP Transaction Id is " + sapTxId);
// Invoke the RfcConfirmTransID method to confirm (commit) the transaction on
// the SAP system. This step is required to complete the transaction. The SAP
// adapter will always return a TranactionalRfcOperationIdentifier, whether
// one was supplied in the call or not.
sapTrfcClient.RfcConfirmTransID(request.TransactionalRfcOperationIdentifier);
Console.WriteLine("SAP Transaction {0} has been committed", sapTxId);
Console.WriteLine("\nHit <RETURN> to end");
Console.ReadLine();
}
catch (ConnectionException cex)
{
Console.WriteLine("Exception occurred connecting to the SAP system");
Console.WriteLine(cex.InnerException.Message);
throw;
}
catch (Exception ex)
{
Console.WriteLine("Exception is: " + ex.Message);
if (ex.InnerException != null)
{
Console.WriteLine("Inner Exception is: " + ex.InnerException.Message);
}
throw;
}
finally
{
// Close the client
if (sapTrfcClient != null)
{
if (sapTrfcClient.State == CommunicationState.Opened)
sapTrfcClient.Close();
else
sapTrfcClient.Abort();
}
}
}
}
}