使用 WCF 服務模型在 SAP 中叫用 BAPIS
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 用戶端類別。 此類別的名稱是以商務物件類型為基礎。 例如,針對銷售訂單商務物件 (商務物件類型BUS2032) ,WCF 用戶端類別為 BapiBUS2032Client。 商務物件中的每個目標 BAPI 都會以產生的 WCF 用戶端類別中的方法表示。 在每個方法中:
SAP 匯出參數會呈現為 out 參數
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 交易
無論是叫用為 RFC 還是商務物件方法的每個 BAPI,都是 SAP 系統上交易 (LUW) 的一部分;和透過相同 SAP 連線接收的每個 BAPI 都是 SAP 系統上相同 BAPI 交易的一部分。 當 SAP 收到連線上的BAPI_TRANSACTION_COMMIT或BAPI_TRANSACTION_ROLLBACK時,SAP 會認可或回復 BAPI 交易。 執行認可或復原之後,透過連線收到的下一個 BAPI 就會開始新的交易。
針對介面卡,每個 WCF 通道都有專用的 SAP 連線。 在 WCF 服務模型中,每個 WCF 用戶端都有一個內部通道,用來將訊息傳送至 SAP 系統。 這表示使用特定 WCF 用戶端叫用的 BAPIs 是 SAP 系統上唯一 BAPI 交易的一部分。 當您使用 WCF 服務模型來叫用 BAPIs 作為商務物件方法時,這會產生重大限制。 因為每個 SAP 商務物件都是由專用 WCF 用戶端類別來表示,所以您無法從兩個不同的商務物件叫用 BAPIs 做為相同交易的一部分。 做法是叫用 BAPIs 作為 RFC 作業。 這是因為新增配接器服務參考外掛程式會產生單一 WCF 用戶端來進行 RFC 作業,因此,使用該用戶端叫用的所有作業都會透過相同的 WCF 通道傳送。
重要
如果您想要在相同的 BAPI 交易中包含來自不同 SAP 商務物件的 BAPIs,您必須使用相同的 WCF 用戶端 () ,以 RFC 作業的形式叫用它們。 您無法將其叫用為商務物件方法。
您可以呼叫BAPI_TRANSACTION_COMMIT或BAPI_TRANSACTION_ROLLBACK,以認可或復原 SAP 系統上的 BAPI 交易。 配接器會顯示這兩個 BAPIs:
在 [基礎] 節點下作為 RFC 作業。
在每個商務物件下。
如需配接器如何在 SAP 上支援 BAPI 交易的詳細資訊,請參閱 SAP 中的 BAPIs 作業。
如何建立叫用 BAPIs 作為商務物件方法的應用程式
本節提供如何叫用 BAPIs 作為商務物件方法的資訊。 您應該遵循相同的基本程式,以將 BAPIs 叫用為 RFC 作業,但您建立以 BAPIs 為目標的 WCF 用戶端作為 RFC 作業,並使用它來叫用每個 BAPI。
若要建立 BAPI 用戶端應用程式,請執行下列步驟。
建立 BAPI 用戶端應用程式
產生 WCF 用戶端類別。 使用 [新增配接器服務參考 Visual Studio 外掛程式] 或 [ServiceModel 中繼資料公用程式工具] (svcutil.exe) 來產生 WCF 用戶端類別 (或類別) ,以您想要使用的商務物件和 BAPIs 為目標。 請務必包含BAPI_TRANSACTION_COMMIT和BAPI_TRANSACTION_ROLLBACK方法, (每個目標商務物件公開的 BAPis) 。 如需如何產生 WCF 用戶端的詳細資訊,請參閱 產生 WCF 用戶端或 SAP 解決方案成品的 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 系統上叫用多個 BAPI。
結束交易的方式如下:
叫用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();
}
}
}
}
}