SAP 适配器将 BAPIs 作为以下内容呈现:
RFC操作。 与任何其他 RFC 一样,BAPIs 显示在“添加适配器服务引用插件”中的 RFC 节点下。
SAP 业务对象的方法。 作为业务对象的方法,BAPIs 通过“添加适配器服务引用插件”中的 BAPI 节点下的业务对象呈现。
无论是将 BAPI 作为 RFC作调用还是作为业务对象方法调用,每个 BAPI 始终是 SAP 系统上 LUW 的一部分。
有关 SAP 适配器如何支持 BAPIs 的概述,请参阅 SAP 中 BAPIs 上的操作。
使用 WCF 服务模型调用 BAPIs 作为业务对象方法时,每个 SAP 业务对象都由 WCF 客户端类表示,该业务对象的 BAPIs 表示为客户端上的方法。 可以使用“添加适配器服务引用 Visual Studio 插件”为特定业务对象生成 WCF 客户端类,该类包含要在代码中调用的每个 BAPI 的方法。 添加适配器服务引用插件还会生成 .NET 类型来封装每个 BAPI 使用的参数和数据类型。 然后,可以创建此 WCF 客户端类的实例,并调用其方法来调用目标 BAPIs。
以下部分介绍如何将 BAPIs 作为业务对象的方法调用,并讨论 WCF 服务模型中如何支持 BAPI 事务。
WCF 客户端类
SAP 适配器为每个业务对象显示不同的服务协定。 这意味着,为每个业务对象创建唯一的 WCF 客户端类。 此类的名字是基于业务对象类型的。 例如,对于 Sales Order 业务对象(业务对象类型BUS2032),WCF 客户端类为 BapiBUS2032Client。 业务对象中的每个目标 BAPI 都表示为生成的 WCF 客户端类中的方法。 在每个方法中:
SAP 导出参数显示为 输出 参数
SAP 调用参数显示为 ref 参数。
复杂的 SAP 类型(如结构)以 .NET 类的形式显示,这些类具有对应于 SAP 类型的字段的属性。 这些类在以下命名空间中定义:microsoft.lobservices.sap._2007._03.Types.Rfc。
对于每个业务对象,BAPI_TRANSACTION_COMMIT和BAPI_TRANSACTION_ROLLBACK都会被暴露出来,并且您应始终将其包含在WCF客户端中。
以下代码显示了为 Sales Order 业务对象生成的 WCF 客户端类的一部分。 此客户端包含调用CREATEFROMDAT2、BAPI_TRANSACTION_COMMIT和BAPI_TRANSACTION_ROLLBACK的方法。 为清楚起见,已省略构造函数和其他代码。
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class BapiBUS2032Client : System.ServiceModel.ClientBase<BapiBUS2032>, BapiBUS2032 {
// Code has been removed for clarity
/// <summary>The Metadata for this RFC was generated using the RFC SDK.</summary>
/// <param name="SALESDOCUMENT">Number of Generated Document</param>
/// <param name="BEHAVE_WHEN_ERROR">Error Handling</param>
/// …
/// <param name="ORDER_TEXT">Texts</param>
/// <param name="PARTNERADDRESSES">BAPI Reference Structure for Addresses (Org./Company)</param>
/// <param name="RETURN">Return Messages</param>
/// <returns></returns>
public string 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.BAPISDHD1X ORDER_HEADER_INX,
string SALESDOCUMENTIN,
microsoft.lobservices.sap._2007._03.Types.Rfc.BAPI_SENDER SENDER,
string TESTRUN,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPIPAREX[] EXTENSIONIN,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPICCARD[] ORDER_CCARD,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPICUBLB[] ORDER_CFGS_BLOB,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPICUINS[] ORDER_CFGS_INST,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPICUPRT[] ORDER_CFGS_PART_OF,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPICUCFG[] ORDER_CFGS_REF,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPICUREF[] ORDER_CFGS_REFINST,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPICUVAL[] ORDER_CFGS_VALUE,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPICUVK[] ORDER_CFGS_VK,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPICOND[] ORDER_CONDITIONS_IN,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPICONDX[] ORDER_CONDITIONS_INX,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPISDITM[] ORDER_ITEMS_IN,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPISDITMX[] ORDER_ITEMS_INX,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPISDKEY[] ORDER_KEYS,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPIPARNR[] ORDER_PARTNERS,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPISCHDL[] ORDER_SCHEDULES_IN,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPISCHDLX[] ORDER_SCHEDULES_INX,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPISDTEXT[] ORDER_TEXT,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPIADDR1[] PARTNERADDRESSES,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPIRET2[] RETURN) { ...}
/// <summary>The Metadata for this RFC was generated using the RFC SDK.</summary>
/// <param name="RETURN">Confirmations</param>
/// <param name="WAIT">Using the command `COMMIT AND WAIT`</param>
/// <returns></returns>
public microsoft.lobservices.sap._2007._03.Types.Rfc.BAPIRET2 BAPI_TRANSACTION_COMMIT(string WAIT) { ... }
/// <summary>The Metadata for this RFC was generated using the RFC SDK.</summary>
/// <param name="RETURN">Confirmations</param>
/// <returns></returns>
public microsoft.lobservices.sap._2007._03.Types.Rfc.BAPIRET2 BAPI_TRANSACTION_ROLLBACK() { ... }
}
WCF 服务模型中的 BAPI 事务
每个 BAPI(无论是作为 RFC 调用还是业务对象方法)都是 SAP 系统上的事务(LUW)的一部分;通过同一 SAP 连接接收的每个 BAPI 都是 SAP 系统上相同 BAPI 事务的一部分。 SAP 在接收到连接中的 BAPI_TRANSACTION_COMMIT 或 BAPI_TRANSACTION_ROLLBACK 时,将提交或回滚 BAPI 事务。 执行提交或回滚后,通过连接接收到的下一个 BAPI 将启动一个新事务。
对于适配器,每个 WCF 通道都有一个专用的 SAP 连接。 在 WCF 服务模型中,每个 WCF 客户端都有一个内部通道,用于将消息发送到 SAP 系统。 这意味着使用特定 WCF 客户端调用的 BAPIs 是 SAP 系统上唯一 BAPI 事务的一部分。 当使用 WCF 服务模型将 BAPIs 作为业务对象方法调用时,这会施加重大限制。 由于每个 SAP 业务对象都由专用 WCF 客户端类表示,因此不能从两个不同的业务对象调用 BAPIs 作为同一事务的一部分。 解决方法是将 BAPI 作为 RFC 调用。 这是因为添加适配器服务引用插件为 RFC 操作生成单个 WCF 客户端,因此,使用该客户端调用的所有操作都通过同一 WCF 通道发送。
重要
如果要在同一 BAPI 事务中包含来自不同 SAP 业务对象的 BAPIs,则必须将它们作为 RFC作调用(使用相同的 WCF 客户端)。 不能将它们作为业务对象方法调用。
您可以调用函数 BAPI_TRANSACTION_COMMIT 或 BAPI_TRANSACTION_ROLLBACK,以在 SAP 系统上提交或回滚 BAPI 事务。 适配器显示这两个 BAPIs:
在基础节点下作为 RFC 操作。
在每个业务对象下。
有关适配器如何支持 SAP 上的 BAPI 事务的详细信息,请参阅 SAP 中 BAPI 的操作。
如何创建将 BAPIs 作为业务对象方法调用的应用程序
本部分介绍如何将 BAPIs 作为业务对象的方法调用。 应遵循相同的基本过程来调用 BAPIs 作为 RFC 操作,只不过创建一个针对 BAPIs 作为 RFC 操作的 WCF 客户端,并使用它来调用每个 BAPI。
若要创建 BAPI 客户端应用程序,请执行以下步骤。
创建 BAPI 客户端应用程序
生成 WCF 客户端类。 使用“添加适配器服务引用 Visual Studio 插件”或 ServiceModel 元数据实用工具(svcutil.exe)生成针对您要使用的业务对象和 BAPI 的 WCF 客户端类(或多个类)。 请务必包括为每个目标业务对象公开的BAPI_TRANSACTION_COMMIT和BAPI_TRANSACTION_ROLLBACK方法(BAPIs)。 有关如何生成 WCF 客户端的详细信息,请参阅 生成适用于 SAP 解决方案项目的 WCF 客户端或 WCF 服务协定。
创建步骤 1 中生成的 WCF 客户端类的实例,并创建和配置 WCF 客户端。 配置 WCF 客户端涉及指定客户端将使用的绑定和终结点地址。 可以在代码中强制执行此作,也可以在配置中以声明方式执行此作。 有关如何指定客户端绑定的详细信息,请参阅 为 SAP 系统配置客户端绑定。 以下代码从配置中初始化 Sales Order (BUS2032) SAP 业务对象的 WCF 客户端,并设置 SAP 系统的凭据。
BapiBUS2032Client bapiClient = new BapiBUS2032Client("SAPBinding_BapiBUS2032"); bapiClient.ClientCredentials.UserName.UserName = "YourUserName"; bapiClient.ClientCredentials.UserName.Password = "YourPassword";
打开 WCF 客户端。
bapiClient.Open();
在步骤 2 中创建的 WCF 客户端上调用方法,以调用 SAP 系统上的相应 BAPIs。 可以在 SAP 系统上调用多个 BAPIs。
结束事务的方式可以通过以下步骤:
调用BAPI_TRANSACTION_COMMIT方法提交事务。
bapiClient.BAPI_TRANSACTION_COMMIT("X");
调用 BAPI_TRANSACTION_ROLLBACK 方法来回滚事务。
bapiClient.BAPI_TRANSACTION_ROLLBACK();
关闭 WCF 客户端。
bapiClient.Close();
示例:
以下示例在 Sales Order 业务对象上调用 CREATEFROMDAT2 BAPI。 它多次调用 BAPI,然后调用BAPI_TRANSACTION_COMMIT提交事务。 如果在调用 BAPI 时发生错误,则会在异常处理程序中调用BAPI_TRANSACTION_ROLLBACK以回滚事务。
CREATEFROMDAT2方法采用许多参数;为了简洁起见,本示例中省略了这些内容。 可以找到一个示例,该示例演示了Microsoft BizTalk 适配器包随附的示例中的 BAPI 事务。 有关详细信息,请参阅 SAP 适配器的示例。
using System;
using System.Collections.Generic;
using System.Text;
// Add WCF, Adapter LOB SDK, and SAP Adapter namepaces
using System.ServiceModel;
using Microsoft.Adapters.SAP;
using Microsoft.ServiceModel.Channels;
// Include this namespace for Adapter LOB SDK and SAP exceptions
using Microsoft.ServiceModel.Channels.Common;
using microsoft.lobservices.sap._2007._03.Types.Rfc;
// This Example demonstrates BAPI transactions. Two sales orders are
// created using the CREATEFROMDAT2 method of a SAP Business Object.
// After the orders are created, the BAPI transaction is committed.
// If an exception occurs when sending the BAPIs, the BAPI transaction is
// rolled back.
//
namespace SapBapiTxClientSM
{
class Program
{
static void Main(string[] args)
{
// Create the BAPI client from the generated endpoint configuration.
BapiBUS2032Client bapiClient = null;
Console.WriteLine("BAPI transaction sample started");
Console.WriteLine("\nCreating business object client");
try
{
bapiClient = new BapiBUS2032Client("SAPBinding_BapiBUS2032");
bapiClient.ClientCredentials.UserName.UserName = "YourUserName";
bapiClient.ClientCredentials.UserName.Password = "YourPassword";
// Open the BAPI Client
bapiClient.Open();
...
// send first BAPI
try
{
string salesDocNumber1 = bapiClient.CREATEFROMDAT2(
...
// parameters ommitted
...
);
}
catch (Exception ex)
{
bapiClient.BAPI_TRANSACTION_ROLLBACK();
throw;
}
...
// send second BAPI
try
{
string salesDocNumber1 = bapiClient.CREATEFROMDAT2(
...
// parameters omitted
...
);
}
catch (Exception ex)
{
bapiClient.BAPI_TRANSACTION_ROLLBACK();
throw;
}
...
// Commit BAPI Transaction
try
{
bapiClient.BAPI_TRANSACTION.Commit();
}
catch (Exception ex)
{
bapiClient.BAPI_TRANSACTION_ROLLBACK();
throw;
}
...
}
catch (ConnectionException cex)
{
// Get here if problem connecting to the SAP system
Console.WriteLine("Exception occurred connecting to the SAP system");
Console.WriteLine(cex.InnerException.Message);
}
catch (TargetSystemException tex)
{
// Get here if the SAP system returns an exception
Console.WriteLine("Exception occurred on the SAP System");
Console.WriteLine(tex.InnerException.Message);
}
catch (Exception ex)
{
Console.WriteLine("Exception is: " + ex.Message);
if (ex.InnerException != null)
{
Console.WriteLine("Inner Exception is: " + ex.InnerException.Message);
}
}
finally
{
// Close the client when finished
if (bapiClient != null)
{
if (bapiClient.State == CommunicationState.Opened)
bapiClient.Close();
else
bapiClient.Abort();
}
}
}
}
}